diff options
Diffstat (limited to 'sw/source/ui/table')
-rw-r--r-- | sw/source/ui/table/autoformatpreview.cxx | 467 | ||||
-rw-r--r-- | sw/source/ui/table/colwd.cxx | 75 | ||||
-rw-r--r-- | sw/source/ui/table/convert.cxx | 203 | ||||
-rw-r--r-- | sw/source/ui/table/instable.cxx | 294 | ||||
-rw-r--r-- | sw/source/ui/table/mergetbl.cxx | 40 | ||||
-rw-r--r-- | sw/source/ui/table/rowht.cxx | 72 | ||||
-rw-r--r-- | sw/source/ui/table/splittbl.cxx | 48 | ||||
-rw-r--r-- | sw/source/ui/table/tabledlg.cxx | 1762 | ||||
-rw-r--r-- | sw/source/ui/table/tautofmt.cxx | 408 |
9 files changed, 3369 insertions, 0 deletions
diff --git a/sw/source/ui/table/autoformatpreview.cxx b/sw/source/ui/table/autoformatpreview.cxx new file mode 100644 index 000000000..2a2318252 --- /dev/null +++ b/sw/source/ui/table/autoformatpreview.cxx @@ -0,0 +1,467 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <editeng/adjustitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/contouritem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <vcl/settings.hxx> +#include <com/sun/star/i18n/BreakIterator.hpp> +#include <comphelper/processfactory.hxx> +#include <svtools/scriptedtext.hxx> +#include <svx/framelink.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/processor2d/processor2dtools.hxx> +#include <strings.hrc> +#include <svtools/colorcfg.hxx> +#include <swmodule.hxx> + +#include <autoformatpreview.hxx> + +#define FRAME_OFFSET 4 + +AutoFormatPreview::AutoFormatPreview() + : maCurrentData(OUString()) + , mbFitWidth(false) + , mbRTL(false) + , maStringJan(SwResId(STR_JAN)) + , maStringFeb(SwResId(STR_FEB)) + , maStringMar(SwResId(STR_MAR)) + , maStringNorth(SwResId(STR_NORTH)) + , maStringMid(SwResId(STR_MID)) + , maStringSouth(SwResId(STR_SOUTH)) + , maStringSum(SwResId(STR_SUM)) +{ + uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext(); + m_xBreak = i18n::BreakIterator::create(xContext); + mxNumFormat.reset(new SvNumberFormatter(xContext, LANGUAGE_SYSTEM)); + + Init(); +} + +void AutoFormatPreview::Resize() +{ + Size aSize = GetOutputSizePixel(); + maPreviousSize = Size(aSize.Width() - 6, aSize.Height() - 30); + mnLabelColumnWidth = (maPreviousSize.Width() - 4) / 4 - 12; + mnDataColumnWidth1 = (maPreviousSize.Width() - 4 - 2 * mnLabelColumnWidth) / 3; + mnDataColumnWidth2 = (maPreviousSize.Width() - 4 - 2 * mnLabelColumnWidth) / 4; + mnRowHeight = (maPreviousSize.Height() - 4) / 5; + NotifyChange(maCurrentData); +} + +void AutoFormatPreview::DetectRTL(SwWrtShell const* pWrtShell) +{ + if (!pWrtShell->IsCursorInTable()) // We haven't created the table yet + mbRTL = AllSettings::GetLayoutRTL(); + else + mbRTL = pWrtShell->IsTableRightToLeft(); +} + +static void lcl_SetFontProperties(vcl::Font& rFont, const SvxFontItem& rFontItem, + const SvxWeightItem& rWeightItem, + const SvxPostureItem& rPostureItem) +{ + rFont.SetFamily(rFontItem.GetFamily()); + rFont.SetFamilyName(rFontItem.GetFamilyName()); + rFont.SetStyleName(rFontItem.GetStyleName()); + rFont.SetCharSet(rFontItem.GetCharSet()); + rFont.SetPitch(rFontItem.GetPitch()); + rFont.SetWeight(rWeightItem.GetValue()); + rFont.SetItalic(rPostureItem.GetValue()); +} + +#define SETONALLFONTS(MethodName, Value) \ + rFont.MethodName(Value); \ + rCJKFont.MethodName(Value); \ + rCTLFont.MethodName(Value); + +void AutoFormatPreview::MakeFonts(vcl::RenderContext const& rRenderContext, sal_uInt8 nIndex, + vcl::Font& rFont, vcl::Font& rCJKFont, vcl::Font& rCTLFont) +{ + const SwBoxAutoFormat& rBoxFormat = maCurrentData.GetBoxFormat(nIndex); + + rFont = rCJKFont = rCTLFont = rRenderContext.GetFont(); + Size aFontSize(rFont.GetFontSize().Width(), 10 * rRenderContext.GetDPIScaleFactor()); + + lcl_SetFontProperties(rFont, rBoxFormat.GetFont(), rBoxFormat.GetWeight(), + rBoxFormat.GetPosture()); + lcl_SetFontProperties(rCJKFont, rBoxFormat.GetCJKFont(), rBoxFormat.GetCJKWeight(), + rBoxFormat.GetCJKPosture()); + lcl_SetFontProperties(rCTLFont, rBoxFormat.GetCTLFont(), rBoxFormat.GetCTLWeight(), + rBoxFormat.GetCTLPosture()); + + SETONALLFONTS(SetUnderline, rBoxFormat.GetUnderline().GetValue()); + SETONALLFONTS(SetOverline, rBoxFormat.GetOverline().GetValue()); + SETONALLFONTS(SetStrikeout, rBoxFormat.GetCrossedOut().GetValue()); + SETONALLFONTS(SetOutline, rBoxFormat.GetContour().GetValue()); + SETONALLFONTS(SetShadow, rBoxFormat.GetShadowed().GetValue()); + SETONALLFONTS(SetColor, rBoxFormat.GetColor().GetValue()); + SETONALLFONTS(SetFontSize, aFontSize); + SETONALLFONTS(SetTransparent, true); +} + +sal_uInt8 AutoFormatPreview::GetFormatIndex(size_t nCol, size_t nRow) const +{ + static const sal_uInt8 pnFormatMap[] + = { 0, 1, 2, 1, 3, 4, 5, 6, 5, 7, 8, 9, 10, 9, 11, 4, 5, 6, 5, 7, 12, 13, 14, 13, 15 }; + return pnFormatMap[maArray.GetCellIndex(nCol, nRow, mbRTL)]; +} + +void AutoFormatPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCol, size_t nRow) +{ + // Output of the cell text: + sal_uLong nNum; + double nVal; + OUString cellString; + sal_uInt8 nIndex = static_cast<sal_uInt8>(maArray.GetCellIndex(nCol, nRow, mbRTL)); + + switch (nIndex) + { + case 1: + cellString = maStringJan; + break; + case 2: + cellString = maStringFeb; + break; + case 3: + cellString = maStringMar; + break; + case 5: + cellString = maStringNorth; + break; + case 10: + cellString = maStringMid; + break; + case 15: + cellString = maStringSouth; + break; + case 4: + case 20: + cellString = maStringSum; + break; + case 6: + case 8: + case 16: + case 18: + nVal = nIndex; + nNum = 5; + goto MAKENUMSTR; + case 17: + case 7: + nVal = nIndex; + nNum = 6; + goto MAKENUMSTR; + case 11: + case 12: + case 13: + nVal = nIndex; + nNum = 12 == nIndex ? 10 : 9; + goto MAKENUMSTR; + case 9: + nVal = 21; + nNum = 7; + goto MAKENUMSTR; + case 14: + nVal = 36; + nNum = 11; + goto MAKENUMSTR; + case 19: + nVal = 51; + nNum = 7; + goto MAKENUMSTR; + case 21: + nVal = 33; + nNum = 13; + goto MAKENUMSTR; + case 22: + nVal = 36; + nNum = 14; + goto MAKENUMSTR; + case 23: + nVal = 39; + nNum = 13; + goto MAKENUMSTR; + case 24: + nVal = 108; + nNum = 15; + goto MAKENUMSTR; + + MAKENUMSTR: + if (maCurrentData.IsValueFormat()) + { + OUString sFormat; + LanguageType eLng, eSys; + maCurrentData.GetBoxFormat(sal_uInt8(nNum)).GetValueFormat(sFormat, eLng, eSys); + + SvNumFormatType nType; + bool bNew; + sal_Int32 nCheckPos; + sal_uInt32 nKey = mxNumFormat->GetIndexPuttingAndConverting(sFormat, eLng, eSys, + nType, bNew, nCheckPos); + const Color* pDummy; + mxNumFormat->GetOutputString(nVal, nKey, cellString, &pDummy); + } + else + cellString = OUString::number(sal_Int32(nVal)); + break; + } + + if (cellString.isEmpty()) + return; + + SvtScriptedTextHelper aScriptedText(rRenderContext); + Size aStrSize; + sal_uInt8 nFormatIndex = GetFormatIndex(nCol, nRow); + const basegfx::B2DRange aCellRange(maArray.GetCellRange(nCol, nRow)); + const tools::Rectangle cellRect( + basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()), + basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY())); + Point aPos = cellRect.TopLeft(); + tools::Long nRightX = 0; + + Size theMaxStrSize(cellRect.GetWidth() - FRAME_OFFSET, cellRect.GetHeight() - FRAME_OFFSET); + if (maCurrentData.IsFont()) + { + vcl::Font aFont, aCJKFont, aCTLFont; + MakeFonts(rRenderContext, nFormatIndex, aFont, aCJKFont, aCTLFont); + aScriptedText.SetFonts(&aFont, &aCJKFont, &aCTLFont); + } + else + aScriptedText.SetDefaultFont(); + + aScriptedText.SetText(cellString, m_xBreak); + aStrSize = aScriptedText.GetTextSize(); + + if (maCurrentData.IsFont() && theMaxStrSize.Height() < aStrSize.Height()) + { + // If the string in this font does not + // fit into the cell, the standard font + // is taken again: + aScriptedText.SetDefaultFont(); + aStrSize = aScriptedText.GetTextSize(); + } + + while (theMaxStrSize.Width() <= aStrSize.Width() && cellString.getLength() > 1) + { + cellString = cellString.copy(0, cellString.getLength() - 1); + aScriptedText.SetText(cellString, m_xBreak); + aStrSize = aScriptedText.GetTextSize(); + } + + nRightX = cellRect.GetWidth() - aStrSize.Width() - FRAME_OFFSET; + + // vertical (always centering): + aPos.AdjustY((mnRowHeight - aStrSize.Height()) / 2); + + // horizontal + if (mbRTL) + aPos.AdjustX(nRightX); + else if (maCurrentData.IsJustify()) + { + const SvxAdjustItem& rAdj = maCurrentData.GetBoxFormat(nFormatIndex).GetAdjust(); + switch (rAdj.GetAdjust()) + { + case SvxAdjust::Left: + aPos.AdjustX(FRAME_OFFSET); + break; + case SvxAdjust::Right: + aPos.AdjustX(nRightX); + break; + default: + aPos.AdjustX((cellRect.GetWidth() - aStrSize.Width()) / 2); + break; + } + } + else + { + // Standard align: + if (nCol == 0 || nIndex == 4) + { + // Text-Label left or sum left aligned + aPos.AdjustX(FRAME_OFFSET); + } + else + { + // numbers/dates right aligned + aPos.AdjustX(nRightX); + } + } + + aScriptedText.DrawText(aPos); +} + +void AutoFormatPreview::DrawBackground(vcl::RenderContext& rRenderContext) +{ + for (size_t nRow = 0; nRow < 5; ++nRow) + { + for (size_t nCol = 0; nCol < 5; ++nCol) + { + SvxBrushItem aBrushItem( + maCurrentData.GetBoxFormat(GetFormatIndex(nCol, nRow)).GetBackground()); + + rRenderContext.Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR); + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(aBrushItem.GetColor()); + const basegfx::B2DRange aCellRange(maArray.GetCellRange(nCol, nRow)); + rRenderContext.DrawRect(tools::Rectangle( + basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()), + basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()))); + rRenderContext.Pop(); + } + } +} + +void AutoFormatPreview::PaintCells(vcl::RenderContext& rRenderContext) +{ + // 1) background + if (maCurrentData.IsBackground()) + DrawBackground(rRenderContext); + + // 2) values + for (size_t nRow = 0; nRow < 5; ++nRow) + for (size_t nCol = 0; nCol < 5; ++nCol) + DrawString(rRenderContext, nCol, nRow); + + // 3) border + if (!maCurrentData.IsFrame()) + return; + + const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D; + std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D( + drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(rRenderContext, + aNewViewInformation2D)); + + if (pProcessor2D) + { + pProcessor2D->process(maArray.CreateB2DPrimitiveArray()); + pProcessor2D.reset(); + } +} + +void AutoFormatPreview::Init() +{ + maArray.Initialize(5, 5); + mnLabelColumnWidth = 0; + mnDataColumnWidth1 = 0; + mnDataColumnWidth2 = 0; + mnRowHeight = 0; + CalcCellArray(false); + CalcLineMap(); +} + +void AutoFormatPreview::CalcCellArray(bool _bFitWidth) +{ + maArray.SetAllColWidths(_bFitWidth ? mnDataColumnWidth2 : mnDataColumnWidth1); + maArray.SetColWidth(0, mnLabelColumnWidth); + maArray.SetColWidth(4, mnLabelColumnWidth); + + maArray.SetAllRowHeights(mnRowHeight); + + maPreviousSize.setWidth(maArray.GetWidth() + 4); + maPreviousSize.setHeight(maArray.GetHeight() + 4); +} + +static void lclSetStyleFromBorder(svx::frame::Style& rStyle, + const ::editeng::SvxBorderLine* pBorder) +{ + rStyle.Set(pBorder, 0.05, 5); +} + +void AutoFormatPreview::CalcLineMap() +{ + for (size_t nRow = 0; nRow < 5; ++nRow) + { + for (size_t nCol = 0; nCol < 5; ++nCol) + { + svx::frame::Style aStyle; + + const SvxBoxItem& rItem + = maCurrentData.GetBoxFormat(GetFormatIndex(nCol, nRow)).GetBox(); + lclSetStyleFromBorder(aStyle, rItem.GetLeft()); + maArray.SetCellStyleLeft(nCol, nRow, aStyle); + lclSetStyleFromBorder(aStyle, rItem.GetRight()); + maArray.SetCellStyleRight(nCol, nRow, aStyle); + lclSetStyleFromBorder(aStyle, rItem.GetTop()); + maArray.SetCellStyleTop(nCol, nRow, aStyle); + lclSetStyleFromBorder(aStyle, rItem.GetBottom()); + maArray.SetCellStyleBottom(nCol, nRow, aStyle); + + // FIXME - uncomment to draw diagonal borders + // lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, true ).GetLine() ); + // maArray.SetCellStyleTLBR( nCol, nRow, aStyle ); + // lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, false ).GetLine() ); + // maArray.SetCellStyleBLTR( nCol, nRow, aStyle ); + } + } +} + +void AutoFormatPreview::NotifyChange(const SwTableAutoFormat& rNewData) +{ + maCurrentData = rNewData; + mbFitWidth = maCurrentData.IsJustify(); // true; //??? + CalcCellArray(mbFitWidth); + CalcLineMap(); + Invalidate(); +} + +void AutoFormatPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + rRenderContext.Push(vcl::PushFlags::ALL); + + DrawModeFlags nOldDrawMode = rRenderContext.GetDrawMode(); + if (rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode()) + rRenderContext.SetDrawMode(DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill + | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient); + + Size theWndSize = rRenderContext.GetOutputSizePixel(); + + vcl::Font aFont(rRenderContext.GetFont()); + aFont.SetTransparent(true); + + rRenderContext.SetFont(aFont); + rRenderContext.SetLineColor(); + const Color& rWinColor = SW_MOD()->GetColorConfig().GetColorValue(::svtools::DOCCOLOR).nColor; + rRenderContext.SetBackground(Wallpaper(rWinColor)); + rRenderContext.SetFillColor(rWinColor); + + // Draw the Frame + Color oldColor = rRenderContext.GetLineColor(); + rRenderContext.SetLineColor(); + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), theWndSize)); + rRenderContext.SetLineColor(oldColor); + + // Center the preview + maArray.SetXOffset(2 + (theWndSize.Width() - maPreviousSize.Width()) / 2); + maArray.SetYOffset(2 + (theWndSize.Height() - maPreviousSize.Height()) / 2); + // Draw cells on virtual device + PaintCells(rRenderContext); + + rRenderContext.SetDrawMode(nOldDrawMode); + rRenderContext.Pop(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/colwd.cxx b/sw/source/ui/table/colwd.cxx new file mode 100644 index 000000000..2440d8696 --- /dev/null +++ b/sw/source/ui/table/colwd.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svtools/unitconv.hxx> +#include <colwd.hxx> +#include <tablemgr.hxx> +#include <wrtsh.hxx> +#include <wdocsh.hxx> +#include <view.hxx> +#include <swmodule.hxx> +#include <usrpref.hxx> + +IMPL_LINK_NOARG(SwTableWidthDlg, LoseFocusHdl, weld::SpinButton&, void) +{ + sal_uInt16 nId = o3tl::narrowing<sal_uInt16>(m_xColNF->get_value()) - 1; + const SwTwips lWidth = m_rFnc.GetColWidth(nId); + m_xWidthMF->set_max(m_xWidthMF->normalize(m_rFnc.GetMaxColWidth(nId)), FieldUnit::TWIP); + m_xWidthMF->set_value(m_xWidthMF->normalize(lWidth), FieldUnit::TWIP); +} + +SwTableWidthDlg::SwTableWidthDlg(weld::Window *pParent, SwTableFUNC &rTableFnc) + : GenericDialogController(pParent, "modules/swriter/ui/columnwidth.ui", "ColumnWidthDialog") + , m_rFnc(rTableFnc) + , m_xColNF(m_xBuilder->weld_spin_button("column")) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM)) +{ + bool bIsWeb = rTableFnc.GetShell() + && (dynamic_cast< const SwWebDocShell* >( + rTableFnc.GetShell()->GetView().GetDocShell()) != nullptr ); + FieldUnit eFieldUnit = SW_MOD()->GetUsrPref( bIsWeb )->GetMetric(); + ::SetFieldUnit(*m_xWidthMF, eFieldUnit); + + m_xColNF->set_max(m_rFnc.GetColCount() + 1); + m_xColNF->set_value(m_rFnc.GetCurColNum() + 1); + + if (m_rFnc.GetColCount() == 0) + m_xWidthMF->set_min(m_xWidthMF->normalize(m_rFnc.GetColWidth(0)), FieldUnit::TWIP); + else + m_xWidthMF->set_min(m_xWidthMF->normalize(MINLAY), FieldUnit::TWIP); + m_xColNF->connect_value_changed(LINK(this, SwTableWidthDlg, LoseFocusHdl)); + LoseFocusHdl(*m_xColNF); +} + +void SwTableWidthDlg::Apply() +{ + m_rFnc.InitTabCols(); + m_rFnc.SetColWidth(o3tl::narrowing<sal_uInt16>(m_xColNF->get_value() - 1), + o3tl::narrowing<sal_uInt16>(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP)))); +} + +short SwTableWidthDlg::run() +{ + short nRet = GenericDialogController::run(); + if (nRet == RET_OK) + Apply(); + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/convert.cxx b/sw/source/ui/table/convert.cxx new file mode 100644 index 000000000..629b6c4f1 --- /dev/null +++ b/sw/source/ui/table/convert.cxx @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <modcfg.hxx> +#include <sfx2/htmlmode.hxx> +#include <viewopt.hxx> +#include <swmodule.hxx> +#include <convert.hxx> +#include <tablemgr.hxx> +#include <view.hxx> +#include <tblafmt.hxx> + +#include <strings.hrc> +#include <swabstdlg.hxx> +#include <swuiexp.hxx> +#include <memory> + +//keep the state of the buttons on runtime +static int nSaveButtonState = -1; // 0: tab, 1: semicolon, 2: paragraph, 3: other, -1: not yet used +static bool bIsKeepColumn = true; +static sal_Unicode uOther = ','; + +void SwConvertTableDlg::GetValues(sal_Unicode& rDelim, SwInsertTableOptions& rInsTableOpts, + SwTableAutoFormat const*& prTAFormat) +{ + if (m_xTabBtn->get_active()) + { + //0x0b mustn't be set when re-converting table into text + bIsKeepColumn = !m_xKeepColumn->get_visible() || m_xKeepColumn->get_active(); + rDelim = bIsKeepColumn ? 0x09 : 0x0b; + nSaveButtonState = 0; + } + else if (m_xSemiBtn->get_active()) + { + rDelim = ';'; + nSaveButtonState = 1; + } + else if (m_xOtherBtn->get_active() && !m_xOtherEd->get_text().isEmpty()) + { + uOther = m_xOtherEd->get_text()[0]; + rDelim = uOther; + nSaveButtonState = 3; + } + else + { + nSaveButtonState = 2; + rDelim = cParaDelim; + if (m_xOtherBtn->get_active()) + { + nSaveButtonState = 3; + uOther = 0; + } + } + + SwInsertTableFlags nInsMode = SwInsertTableFlags::NONE; + if (m_xHeaderCB->get_active()) + nInsMode |= SwInsertTableFlags::Headline; + if (m_xRepeatHeaderCB->get_sensitive() && m_xRepeatHeaderCB->get_active()) + rInsTableOpts.mnRowsToRepeat = m_xRepeatHeaderNF->get_value(); + else + rInsTableOpts.mnRowsToRepeat = 0; + if (!m_xDontSplitCB->get_active()) + nInsMode |= SwInsertTableFlags::SplitLayout; + + if (mxTAutoFormat) + prTAFormat = new SwTableAutoFormat(*mxTAutoFormat); + + rInsTableOpts.mnInsMode = nInsMode; +} + +SwConvertTableDlg::SwConvertTableDlg(SwView& rView, bool bToTable) + : SfxDialogController(rView.GetFrameWeld(), "modules/swriter/ui/converttexttable.ui", + "ConvertTextTableDialog") + , m_xTabBtn(m_xBuilder->weld_radio_button("tabs")) + , m_xSemiBtn(m_xBuilder->weld_radio_button("semicolons")) + , m_xParaBtn(m_xBuilder->weld_radio_button("paragraph")) + , m_xOtherBtn(m_xBuilder->weld_radio_button("other")) + , m_xOtherEd(m_xBuilder->weld_entry("othered")) + , m_xKeepColumn(m_xBuilder->weld_check_button("keepcolumn")) + , m_xOptions(m_xBuilder->weld_container("options")) + , m_xHeaderCB(m_xBuilder->weld_check_button("headingcb")) + , m_xRepeatHeaderCB(m_xBuilder->weld_check_button("repeatheading")) + , m_xRepeatRows(m_xBuilder->weld_container("repeatrows")) + , m_xRepeatHeaderNF(m_xBuilder->weld_spin_button("repeatheadersb")) + , m_xDontSplitCB(m_xBuilder->weld_check_button("dontsplitcb")) + , m_xAutoFormatBtn(m_xBuilder->weld_button("autofmt")) + , pShell(&rView.GetWrtShell()) +{ + if (nSaveButtonState > -1) + { + switch (nSaveButtonState) + { + case 0: + m_xTabBtn->set_active(true); + m_xKeepColumn->set_active(bIsKeepColumn); + break; + case 1: + m_xSemiBtn->set_active(true); + break; + case 2: + m_xParaBtn->set_active(true); + break; + case 3: + m_xOtherBtn->set_active(true); + if (uOther) + m_xOtherEd->set_text(OUString(uOther)); + break; + } + } + if (bToTable) + { + m_xDialog->set_title(SwResId(STR_CONVERT_TEXT_TABLE)); + m_xAutoFormatBtn->connect_clicked(LINK(this, SwConvertTableDlg, AutoFormatHdl)); + m_xAutoFormatBtn->show(); + m_xKeepColumn->show(); + m_xKeepColumn->set_sensitive(m_xTabBtn->get_active()); + } + else + { + //hide insert options + m_xOptions->hide(); + } + m_xKeepColumn->save_state(); + + Link<weld::Toggleable&, void> aLk(LINK(this, SwConvertTableDlg, BtnHdl)); + m_xTabBtn->connect_toggled(aLk); + m_xSemiBtn->connect_toggled(aLk); + m_xParaBtn->connect_toggled(aLk); + m_xOtherBtn->connect_toggled(aLk); + m_xOtherEd->set_sensitive(m_xOtherBtn->get_active()); + + const SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); + + bool bHTMLMode = 0 != (::GetHtmlMode(rView.GetDocShell()) & HTMLMODE_ON); + + SwInsertTableOptions aInsOpts = pModOpt->GetInsTableFlags(bHTMLMode); + SwInsertTableFlags nInsTableFlags = aInsOpts.mnInsMode; + + m_xHeaderCB->set_active(bool(nInsTableFlags & SwInsertTableFlags::Headline)); + m_xRepeatHeaderCB->set_active(aInsOpts.mnRowsToRepeat > 0); + m_xDontSplitCB->set_active(!(nInsTableFlags & SwInsertTableFlags::SplitLayout)); + + m_xHeaderCB->connect_toggled(LINK(this, SwConvertTableDlg, CheckBoxHdl)); + m_xRepeatHeaderCB->connect_toggled(LINK(this, SwConvertTableDlg, RepeatHeaderCheckBoxHdl)); + RepeatHeaderCheckBoxHdl(*m_xRepeatHeaderCB); + CheckBoxHdl(*m_xHeaderCB); +} + +IMPL_LINK_NOARG(SwConvertTableDlg, AutoFormatHdl, weld::Button&, void) +{ + SwAbstractDialogFactory& rFact = swui::GetFactory(); + + ScopedVclPtr<AbstractSwAutoFormatDlg> pDlg( + rFact.CreateSwAutoFormatDlg(m_xDialog.get(), pShell, false, mxTAutoFormat.get())); + if (RET_OK == pDlg->Execute()) + mxTAutoFormat = pDlg->FillAutoFormatOfIndex(); +} + +IMPL_LINK(SwConvertTableDlg, BtnHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + if (m_xTabBtn->get_active()) + m_xKeepColumn->set_state(m_xKeepColumn->get_saved_state()); + else + { + if (m_xKeepColumn->get_sensitive()) + m_xKeepColumn->save_state(); + m_xKeepColumn->set_active(true); + } + m_xKeepColumn->set_sensitive(m_xTabBtn->get_active()); + m_xOtherEd->set_sensitive(m_xOtherBtn->get_active()); +} + +IMPL_LINK_NOARG(SwConvertTableDlg, CheckBoxHdl, weld::Toggleable&, void) +{ + m_xRepeatHeaderCB->set_sensitive(m_xHeaderCB->get_active()); + RepeatHeaderCheckBoxHdl(*m_xRepeatHeaderCB); +} + +IMPL_LINK_NOARG(SwConvertTableDlg, RepeatHeaderCheckBoxHdl, weld::Toggleable&, void) +{ + bool bEnable = m_xHeaderCB->get_active() && m_xRepeatHeaderCB->get_active(); + m_xRepeatRows->set_sensitive(bEnable); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/instable.cxx b/sw/source/ui/table/instable.cxx new file mode 100644 index 000000000..554e4f261 --- /dev/null +++ b/sw/source/ui/table/instable.cxx @@ -0,0 +1,294 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <instable.hxx> +#include <shellres.hxx> +#include <modcfg.hxx> +#include <swmodule.hxx> +#include <sfx2/htmlmode.hxx> +#include <viewopt.hxx> +#include <comphelper/lok.hxx> + + +void SwInsTableDlg::GetValues( OUString& rName, sal_uInt16& rRow, sal_uInt16& rCol, + SwInsertTableOptions& rInsTableOpts, OUString& rAutoName, + std::unique_ptr<SwTableAutoFormat>& prTAFormat ) +{ + SwInsertTableFlags nInsMode = SwInsertTableFlags::NONE; + rName = m_xNameEdit->get_text(); + rRow = m_xRowSpinButton->get_value(); + rCol = m_xColSpinButton->get_value(); + + if (m_xHeaderCB->get_active()) + nInsMode |= SwInsertTableFlags::Headline; + if (m_xRepeatHeaderCB->get_sensitive() && m_xRepeatHeaderCB->get_active()) + rInsTableOpts.mnRowsToRepeat = m_xRepeatHeaderNF->get_value(); + else + rInsTableOpts.mnRowsToRepeat = 0; + if (!m_xDontSplitCB->get_active()) + nInsMode |= SwInsertTableFlags::SplitLayout; + if( m_xTAutoFormat ) + { + prTAFormat.reset(new SwTableAutoFormat( *m_xTAutoFormat )); + rAutoName = prTAFormat->GetName(); + } + + rInsTableOpts.mnInsMode = nInsMode; +} + +IMPL_LINK(SwInsTableDlg, TextFilterHdl, OUString&, rTest, bool) +{ + rTest = m_aTextFilter.filter(rTest); + return true; +} + +SwInsTableDlg::SwInsTableDlg(SwView& rView) + : SfxDialogController(rView.GetFrameWeld(), "modules/swriter/ui/inserttable.ui", "InsertTableDialog") + , m_aTextFilter(" .<>") + , pShell(&rView.GetWrtShell()) + , nEnteredValRepeatHeaderNF(-1) + , m_xNameEdit(m_xBuilder->weld_entry("nameedit")) + , m_xWarning(m_xBuilder->weld_label("lbwarning")) + , m_xColSpinButton(m_xBuilder->weld_spin_button("colspin")) + , m_xRowSpinButton(m_xBuilder->weld_spin_button("rowspin")) + , m_xHeaderCB(m_xBuilder->weld_check_button("headercb")) + , m_xRepeatHeaderCB(m_xBuilder->weld_check_button("repeatcb")) + , m_xRepeatHeaderNF(m_xBuilder->weld_spin_button("repeatheaderspin")) + , m_xRepeatGroup(m_xBuilder->weld_widget("repeatgroup")) + , m_xDontSplitCB(m_xBuilder->weld_check_button("dontsplitcb")) + , m_xInsertBtn(m_xBuilder->weld_button("ok")) + , m_xLbFormat(m_xBuilder->weld_tree_view("formatlbinstable")) + , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "previewinstable", m_aWndPreview)) + , m_xStyleFrame(m_xBuilder->weld_frame("stylesframe")) +{ + if (comphelper::LibreOfficeKit::isActive()) + m_xStyleFrame->hide(); + + const int nWidth = m_xLbFormat->get_approximate_digit_width() * 32; + const int nHeight = m_xLbFormat->get_height_rows(8); + m_xLbFormat->set_size_request(nWidth, nHeight); + m_xWndPreview->set_size_request(nWidth, nHeight); + + m_xNameEdit->connect_insert_text(LINK(this, SwInsTableDlg, TextFilterHdl)); + m_xNameEdit->set_text(pShell->GetUniqueTableName()); + m_xNameEdit->connect_changed(LINK(this, SwInsTableDlg, ModifyName)); + m_xRowSpinButton->connect_changed(LINK(this, SwInsTableDlg, ModifyRowCol)); + m_xColSpinButton->connect_changed(LINK(this, SwInsTableDlg, ModifyRowCol)); + + m_xInsertBtn->connect_clicked(LINK(this, SwInsTableDlg, OKHdl)); + + bool bHTMLMode = 0 != (::GetHtmlMode(rView.GetDocShell())&HTMLMODE_ON); + const SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); + + SwInsertTableOptions aInsOpts = pModOpt->GetInsTableFlags(bHTMLMode); + SwInsertTableFlags nInsTableFlags = aInsOpts.mnInsMode; + + m_xHeaderCB->set_active(bool(nInsTableFlags & SwInsertTableFlags::Headline)); + m_xRepeatHeaderCB->set_active(aInsOpts.mnRowsToRepeat > 0); + if (bHTMLMode) + m_xDontSplitCB->hide(); + else + m_xDontSplitCB->set_active(!(nInsTableFlags & SwInsertTableFlags::SplitLayout)); + + m_xRepeatHeaderNF->connect_value_changed( LINK( this, SwInsTableDlg, ModifyRepeatHeaderNF_Hdl ) ); + m_xHeaderCB->connect_toggled( LINK( this, SwInsTableDlg, CheckBoxHdl ) ); + m_xRepeatHeaderCB->connect_toggled( LINK( this, SwInsTableDlg, RepeatHeaderCheckBoxHdl ) ); + RepeatHeaderCheckBoxHdl(*m_xRepeatHeaderCB); + CheckBoxHdl(*m_xHeaderCB); + + sal_Int64 nMax = m_xRowSpinButton->get_value(); + if( nMax <= 1 ) + nMax = 1; + else + --nMax; + m_xRepeatHeaderNF->set_max( nMax ); + + InitAutoTableFormat(); + m_xWarning->set_label_type(weld::LabelType::Warning); +} + +void SwInsTableDlg::InitAutoTableFormat() +{ + m_aWndPreview.DetectRTL(pShell); + + m_xLbFormat->connect_changed(LINK(this, SwInsTableDlg, SelFormatHdl)); + + m_xTableTable.reset(new SwTableAutoFormatTable); + m_xTableTable->Load(); + + // Add "- none -" style autoformat table. + m_xLbFormat->append_text(SwViewShell::GetShellRes()->aStrNone); // Insert to listbox + + // Add other styles of autoformat tables. + for (sal_uInt8 i = 0, nCount = static_cast<sal_uInt8>(m_xTableTable->size()); + i < nCount; i++) + { + SwTableAutoFormat const& rFormat = (*m_xTableTable)[ i ]; + m_xLbFormat->append_text(rFormat.GetName()); + if (m_xTAutoFormat && rFormat.GetName() == m_xTAutoFormat->GetName()) + lbIndex = i; + } + + // Change this min variable if you add autotable manually. + minTableIndexInLb = 1; + maxTableIndexInLb = minTableIndexInLb + static_cast<sal_uInt8>(m_xTableTable->size()); + lbIndex = 0; + m_xLbFormat->select( lbIndex ); + tbIndex = lbIndexToTableIndex(lbIndex); + + SelFormatHdl( *m_xLbFormat ); +} + +sal_uInt8 SwInsTableDlg::lbIndexToTableIndex( const sal_uInt8 listboxIndex ) +{ + if( minTableIndexInLb != maxTableIndexInLb && + minTableIndexInLb <= listboxIndex && + listboxIndex < maxTableIndexInLb ) + { + return listboxIndex - minTableIndexInLb; + } + + return 255; +} + +static void lcl_SetProperties( SwTableAutoFormat* pTableAutoFormat, bool bVal ) +{ + pTableAutoFormat->SetFont( bVal ); + pTableAutoFormat->SetJustify( bVal ); + pTableAutoFormat->SetFrame( bVal ); + pTableAutoFormat->SetBackground( bVal ); + pTableAutoFormat->SetValueFormat( bVal ); + pTableAutoFormat->SetWidthHeight( bVal ); +} + +IMPL_LINK_NOARG(SwInsTableDlg, SelFormatHdl, weld::TreeView&, void) +{ + // Get index of selected item from the listbox + lbIndex = static_cast<sal_uInt8>(m_xLbFormat->get_selected_index()); + tbIndex = lbIndexToTableIndex( lbIndex ); + + // To understand this index mapping, look InitAutoTableFormat function to + // see how listbox item is implemented. + if( tbIndex < 255 ) + m_aWndPreview.NotifyChange( (*m_xTableTable)[tbIndex] ); + else + { + SwTableAutoFormat aTmp( SwViewShell::GetShellRes()->aStrNone ); + lcl_SetProperties( &aTmp, false ); + + m_aWndPreview.NotifyChange( aTmp ); + } +} + +IMPL_LINK_NOARG(SwInsTableDlg, OKHdl, weld::Button&, void) +{ + if( tbIndex < 255 ) + pShell->SetTableStyle((*m_xTableTable)[tbIndex]); + + if( tbIndex < 255 ) + { + if( m_xTAutoFormat ) + *m_xTAutoFormat = (*m_xTableTable)[ tbIndex ]; + else + m_xTAutoFormat.reset(new SwTableAutoFormat( (*m_xTableTable)[ tbIndex ] )); + } + else + { + m_xTAutoFormat.reset(new SwTableAutoFormat( SwViewShell::GetShellRes()->aStrNone )); + lcl_SetProperties( m_xTAutoFormat.get(), false ); + } + + m_xDialog->response(RET_OK); +} + +IMPL_LINK( SwInsTableDlg, ModifyName, weld::Entry&, rEdit, void ) +{ + OUString sTableName = rEdit.get_text(); + m_xInsertBtn->set_sensitive(pShell->GetTableStyle(sTableName) == nullptr); +} + +// We use weld::Entry's "changed" notification here, not weld::SpinButton's "value_changed", because +// the latter only fires after the control looses focus; so the notification would not fire during +// typing a big number, so that user typing it and immediately clicking "Insert" would not see the +// warning. +// Since the notification is called in weld::Entry context, we can only rely on what's available for +// used weld::Entry's notification; specifically, we have to call spin buttons' get_text() instead +// of get_value(), because the latter is not guaranteed to return an up-to-date value at this point +// (depends on vcl plugin used). +IMPL_LINK( SwInsTableDlg, ModifyRowCol, weld::Entry&, rEdit, void ) +{ + sal_Int64 nRow = m_xRowSpinButton->get_text().toInt64(); + sal_Int64 nCol = m_xColSpinButton->get_text().toInt64(); + if (nRow > 255) + { + m_xRowSpinButton->set_message_type(weld::EntryMessageType::Warning); + m_xWarning->set_visible(true); + } + else + { + m_xRowSpinButton->set_message_type(weld::EntryMessageType::Normal); + } + if (nCol > 63) + { + m_xColSpinButton->set_message_type(weld::EntryMessageType::Warning); + m_xWarning->set_visible(true); + } + else + { + m_xColSpinButton->set_message_type(weld::EntryMessageType::Normal); + } + if (nRow <= 255 && nCol <= 63) + { + m_xWarning->set_visible(false); + } + if (&rEdit == m_xColSpinButton.get()) + return; + + if(!nRow) + nRow = 1; + + // adjust depending NF for repeated rows + sal_Int64 nMax = ( nRow == 1 )? 1 : nRow - 1 ; + sal_Int64 nActVal = m_xRepeatHeaderNF->get_value(); + + m_xRepeatHeaderNF->set_max( nMax ); + + if( nActVal > nMax ) + m_xRepeatHeaderNF->set_value( nMax ); + else if( nActVal < nEnteredValRepeatHeaderNF ) + m_xRepeatHeaderNF->set_value(std::min(nEnteredValRepeatHeaderNF, nMax)); +} + +IMPL_LINK_NOARG(SwInsTableDlg, CheckBoxHdl, weld::Toggleable&, void) +{ + m_xRepeatHeaderCB->set_sensitive(m_xHeaderCB->get_active()); + RepeatHeaderCheckBoxHdl(*m_xRepeatHeaderCB); +} + +IMPL_LINK_NOARG(SwInsTableDlg, RepeatHeaderCheckBoxHdl, weld::Toggleable&, void) +{ + m_xRepeatGroup->set_sensitive(m_xHeaderCB->get_active() && m_xRepeatHeaderCB->get_active()); +} + +IMPL_LINK_NOARG(SwInsTableDlg, ModifyRepeatHeaderNF_Hdl, weld::SpinButton&, void) +{ + nEnteredValRepeatHeaderNF = m_xRepeatHeaderNF->get_value(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/mergetbl.cxx b/sw/source/ui/table/mergetbl.cxx new file mode 100644 index 000000000..c715b8a5f --- /dev/null +++ b/sw/source/ui/table/mergetbl.cxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <mergetbl.hxx> + +SwMergeTableDlg::SwMergeTableDlg(weld::Window* pParent, bool& rWithPrev) + : GenericDialogController(pParent, "modules/swriter/ui/mergetabledialog.ui", "MergeTableDialog") + , m_rMergePrev(rWithPrev) + , m_xMergePrevRB(m_xBuilder->weld_radio_button("prev")) +{ + m_xMergePrevRB->set_active(true); +} + +void SwMergeTableDlg::Apply() { m_rMergePrev = m_xMergePrevRB->get_active(); } + +short SwMergeTableDlg::run() +{ + int nRet = GenericDialogController::run(); + if (nRet == RET_OK) + Apply(); + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/rowht.cxx b/sw/source/ui/table/rowht.cxx new file mode 100644 index 000000000..f46297bf7 --- /dev/null +++ b/sw/source/ui/table/rowht.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svtools/unitconv.hxx> + +#include <fmtfsize.hxx> +#include <swtypes.hxx> +#include <rowht.hxx> +#include <wrtsh.hxx> +#include <wdocsh.hxx> +#include <view.hxx> +#include <swmodule.hxx> +#include <usrpref.hxx> + +void SwTableHeightDlg::Apply() +{ + SwTwips nHeight = static_cast< SwTwips >(m_xHeightEdit->denormalize(m_xHeightEdit->get_value(FieldUnit::TWIP))); + SwFormatFrameSize aSz(SwFrameSize::Fixed, 0, nHeight); + + SwFrameSize eFrameSize = m_xAutoHeightCB->get_active() ? SwFrameSize::Minimum : SwFrameSize::Fixed; + if(eFrameSize != aSz.GetHeightSizeType()) + { + aSz.SetHeightSizeType(eFrameSize); + } + m_rSh.SetRowHeight(aSz); +} + +SwTableHeightDlg::SwTableHeightDlg(weld::Window *pParent, SwWrtShell &rS) + : GenericDialogController(pParent, "modules/swriter/ui/rowheight.ui", "RowHeightDialog") + , m_rSh(rS) + , m_xHeightEdit(m_xBuilder->weld_metric_spin_button("heightmf", FieldUnit::CM)) + , m_xAutoHeightCB(m_xBuilder->weld_check_button("fit")) +{ + FieldUnit eFieldUnit = SW_MOD()->GetUsrPref( dynamic_cast< const SwWebDocShell*>( + m_rSh.GetView().GetDocShell() ) != nullptr )->GetMetric(); + ::SetFieldUnit(*m_xHeightEdit, eFieldUnit); + + m_xHeightEdit->set_min(MINLAY, FieldUnit::TWIP); + std::unique_ptr<SwFormatFrameSize> pSz = m_rSh.GetRowHeight(); + if (pSz) + { + auto nHeight = pSz->GetHeight(); + m_xAutoHeightCB->set_active(pSz->GetHeightSizeType() != SwFrameSize::Fixed); + m_xHeightEdit->set_value(m_xHeightEdit->normalize(nHeight), FieldUnit::TWIP); + } +} + +short SwTableHeightDlg::run() +{ + short nRet = GenericDialogController::run(); + if (nRet == RET_OK) + Apply(); + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/splittbl.cxx b/sw/source/ui/table/splittbl.cxx new file mode 100644 index 000000000..0deb5d030 --- /dev/null +++ b/sw/source/ui/table/splittbl.cxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <wrtsh.hxx> +#include <splittbl.hxx> +#include <tblenum.hxx> + +SwSplitTableDlg::SwSplitTableDlg(weld::Window* pParent, SwWrtShell& rSh) + : GenericDialogController(pParent, "modules/swriter/ui/splittable.ui", "SplitTableDialog") + , m_xContentCopyRB(m_xBuilder->weld_radio_button("copyheading")) + , m_xBoxAttrCopyWithParaRB(m_xBuilder->weld_radio_button("customheadingapplystyle")) + , m_xBoxAttrCopyNoParaRB(m_xBuilder->weld_radio_button("customheading")) + , m_xBorderCopyRB(m_xBuilder->weld_radio_button("noheading")) + , rShell(rSh) + , m_nSplit(SplitTable_HeadlineOption::ContentCopy) +{ +} + +void SwSplitTableDlg::Apply() +{ + m_nSplit = SplitTable_HeadlineOption::ContentCopy; + if (m_xBoxAttrCopyWithParaRB->get_active()) + m_nSplit = SplitTable_HeadlineOption::BoxAttrAllCopy; + else if (m_xBoxAttrCopyNoParaRB->get_active()) + m_nSplit = SplitTable_HeadlineOption::BoxAttrCopy; + else if (m_xBorderCopyRB->get_active()) + m_nSplit = SplitTable_HeadlineOption::BorderCopy; + + rShell.SplitTable(m_nSplit); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/tabledlg.cxx b/sw/source/ui/table/tabledlg.cxx new file mode 100644 index 000000000..329626663 --- /dev/null +++ b/sw/source/ui/table/tabledlg.cxx @@ -0,0 +1,1762 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <hintids.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <editeng/keepitem.hxx> +#include <editeng/formatbreakitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svl/ctloptions.hxx> +#include <swmodule.hxx> +#include <fmtpdsc.hxx> +#include <fmtlsplt.hxx> + +#include <svtools/htmlcfg.hxx> +#include <fmtrowsplt.hxx> +#include <sfx2/htmlmode.hxx> +#include <sfx2/sfxdlg.hxx> + +#include <strings.hrc> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> + +#include <wrtsh.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <uitool.hxx> +#include <tabledlg.hxx> +#include "../../uibase/table/tablepg.hxx" +#include <tablemgr.hxx> +#include <pagedesc.hxx> +#include <uiitems.hxx> +#include <poolfmt.hxx> +#include <swtablerep.hxx> +#include <SwStyleNameMapper.hxx> + +#include <cmdid.h> +#include <svx/dialogs.hrc> +#include <svx/flagsdef.hxx> +#include <osl/diagnose.h> + +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> + +using namespace ::com::sun::star; + +SwFormatTablePage::SwFormatTablePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/formattablepage.ui", "FormatTablePage", &rSet) + , pTableData(nullptr) + , nSaveWidth(0) + , nMinTableWidth(MINLAY) + , bModified(false) + , bFull(false) + , bHtmlMode(false) + , m_xNameED(m_xBuilder->weld_entry("name")) + , m_xWidthFT(m_xBuilder->weld_label("widthft")) + , m_xWidthMF(new SwPercentField(m_xBuilder->weld_metric_spin_button("widthmf", FieldUnit::CM))) + , m_xRelWidthCB(m_xBuilder->weld_check_button("relwidth")) + , m_xFullBtn(m_xBuilder->weld_radio_button("full")) + , m_xLeftBtn(m_xBuilder->weld_radio_button("left")) + , m_xFromLeftBtn(m_xBuilder->weld_radio_button("fromleft")) + , m_xRightBtn(m_xBuilder->weld_radio_button("right")) + , m_xCenterBtn(m_xBuilder->weld_radio_button("center")) + , m_xFreeBtn(m_xBuilder->weld_radio_button("free")) + , m_xLeftFT(m_xBuilder->weld_label("leftft")) + , m_xLeftMF(new SwPercentField(m_xBuilder->weld_metric_spin_button("leftmf", FieldUnit::CM))) + , m_xRightFT(m_xBuilder->weld_label("rightft")) + , m_xRightMF(new SwPercentField(m_xBuilder->weld_metric_spin_button("rightmf", FieldUnit::CM))) + , m_xTopFT(m_xBuilder->weld_label("aboveft")) + , m_xTopMF(m_xBuilder->weld_metric_spin_button("abovemf", FieldUnit::CM)) + , m_xBottomFT(m_xBuilder->weld_label("belowft")) + , m_xBottomMF(m_xBuilder->weld_metric_spin_button("belowmf", FieldUnit::CM)) + , m_xTextDirectionLB(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("textdirection"))) + , m_xProperties(m_xBuilder->weld_widget("properties")) +{ + m_xWidthMF->GetMetricFieldRange(m_nOrigWidthMin, m_nOrigWidthMax); + m_xLeftMF->GetMetricFieldRange(m_nOrigLeftMin, m_nOrigLeftMax); + m_xRightMF->GetMetricFieldRange(m_nOrigRightMin, m_nOrigRightMax); + + //lock these to initial sizes so they don't change on percent to non percent change + Size aPrefSize(m_xLeftMF->get()->get_preferred_size()); + m_xLeftMF->get()->set_size_request(aPrefSize.Width(), aPrefSize.Height()); + m_xRightMF->get()->set_size_request(aPrefSize.Width(), aPrefSize.Height()); + m_xWidthMF->get()->set_size_request(aPrefSize.Width(), aPrefSize.Height()); + + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); + m_xTextDirectionLB->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + + SetExchangeSupport(); + + if(const SfxUInt16Item* pModeItem = rSet.GetItemIfSet(SID_HTML_MODE, false)) + bHtmlMode = 0 != (pModeItem->GetValue() & HTMLMODE_ON); + + bool bCTL = SW_MOD()->GetCTLOptions().IsCTLFontEnabled(); + m_xProperties->set_visible(!bHtmlMode && bCTL); + + Init(); +} + +SwFormatTablePage::~SwFormatTablePage() +{ +} + +void SwFormatTablePage::Init() +{ + m_xLeftMF->SetMetricFieldMin(-999999); + m_xRightMF->SetMetricFieldMin(-999999); + + //handler + Link<weld::Toggleable&,void> aLk2 = LINK( this, SwFormatTablePage, AutoClickHdl ); + m_xFullBtn->connect_toggled( aLk2 ); + m_xFreeBtn->connect_toggled( aLk2 ); + m_xLeftBtn->connect_toggled( aLk2 ); + m_xFromLeftBtn->connect_toggled( aLk2 ); + m_xRightBtn->connect_toggled( aLk2 ); + m_xCenterBtn->connect_toggled( aLk2 ); + + Link<weld::MetricSpinButton&,void> aLk = LINK(this, SwFormatTablePage, ValueChangedHdl); + m_xTopMF->connect_value_changed(aLk); + m_xBottomMF->connect_value_changed(aLk); + m_xRightMF->connect_value_changed(aLk); + m_xLeftMF->connect_value_changed(aLk); + m_xWidthMF->connect_value_changed(aLk); + + m_xRelWidthCB->connect_toggled(LINK( this, SwFormatTablePage, RelWidthClickHdl )); +} + +IMPL_LINK( SwFormatTablePage, RelWidthClickHdl, weld::Toggleable&, rBtn, void ) +{ + OSL_ENSURE(pTableData, "table data not available?"); + bool bIsChecked = rBtn.get_active(); + sal_Int64 nLeft = m_xLeftMF->DenormalizePercent(m_xLeftMF->get_value(FieldUnit::TWIP)); + sal_Int64 nRight = m_xRightMF->DenormalizePercent(m_xRightMF->get_value(FieldUnit::TWIP)); + m_xWidthMF->ShowPercent(bIsChecked); + m_xLeftMF->ShowPercent(bIsChecked); + m_xRightMF->ShowPercent(bIsChecked); + + if (bIsChecked) + { + m_xWidthMF->SetRefValue(pTableData->GetSpace()); + m_xLeftMF->SetRefValue(pTableData->GetSpace()); + m_xRightMF->SetRefValue(pTableData->GetSpace()); + m_xLeftMF->SetMetricFieldMin(0); //will be overwritten by the Percentfield + m_xRightMF->SetMetricFieldMin(0); //ditto + m_xLeftMF->SetMetricFieldMax(99); + m_xRightMF->SetMetricFieldMax(99); + m_xLeftMF->set_value(m_xLeftMF->NormalizePercent(nLeft ), FieldUnit::TWIP ); + m_xRightMF->set_value(m_xRightMF->NormalizePercent(nRight ), FieldUnit::TWIP ); + } + else + ModifyHdl(*m_xLeftMF->get()); //correct values again + + if (m_xFreeBtn->get_active()) + { + bool bEnable = !rBtn.get_active(); + m_xRightMF->set_sensitive(bEnable); + m_xRightFT->set_sensitive(bEnable); + } + bModified = true; +} + +IMPL_LINK_NOARG(SwFormatTablePage, AutoClickHdl, weld::Toggleable&, void) +{ + bool bRestore = true, + bLeftEnable = false, + bRightEnable= false, + bWidthEnable= false, + bOthers = true; + if (m_xFullBtn->get_active()) + { + m_xLeftMF->set_value(0); + m_xRightMF->set_value(0); + nSaveWidth = static_cast<SwTwips>(m_xWidthMF->DenormalizePercent(m_xWidthMF->get_value(FieldUnit::TWIP))); + m_xWidthMF->set_value(m_xWidthMF->NormalizePercent(pTableData->GetSpace()), FieldUnit::TWIP); + bFull = true; + bRestore = false; + } + else if (m_xLeftBtn->get_active()) + { + bRightEnable = bWidthEnable = true; + m_xLeftMF->set_value(0); + } + else if (m_xFromLeftBtn->get_active()) + { + bLeftEnable = bWidthEnable = true; + m_xRightMF->set_value(0); + } + else if (m_xRightBtn->get_active()) + { + bLeftEnable = bWidthEnable = true; + m_xRightMF->set_value(0); + } + else if (m_xCenterBtn->get_active()) + { + bLeftEnable = bWidthEnable = true; + } + else if (m_xFreeBtn->get_active()) + { + RightModify(); + bLeftEnable = true; + bWidthEnable = true; + bOthers = false; + } + m_xLeftMF->set_sensitive(bLeftEnable); + m_xLeftFT->set_sensitive(bLeftEnable); + m_xWidthMF->set_sensitive(bWidthEnable); + m_xWidthFT->set_sensitive(bWidthEnable); + if ( bOthers ) + { + m_xRightMF->set_sensitive(bRightEnable); + m_xRightFT->set_sensitive(bRightEnable); + m_xRelWidthCB->set_sensitive(bWidthEnable); + } + + if(bFull && bRestore) + { + //After being switched on automatic, the width was pinned + //in order to restore the width while switching back to. + bFull = false; + m_xWidthMF->set_value(m_xWidthMF->NormalizePercent(nSaveWidth ), FieldUnit::TWIP ); + } + ModifyHdl(*m_xWidthMF->get()); + bModified = true; +} + +void SwFormatTablePage::RightModify() +{ + if (!m_xFreeBtn->get_active()) + return; + + bool bEnable = m_xRightMF->get_value() == 0; + m_xRelWidthCB->set_sensitive(bEnable); + if ( !bEnable ) + { + m_xRelWidthCB->set_active(false); + RelWidthClickHdl(*m_xRelWidthCB); + } + bEnable = m_xRelWidthCB->get_active(); + m_xRightMF->set_sensitive(!bEnable); + m_xRightFT->set_sensitive(!bEnable); +} + +IMPL_LINK( SwFormatTablePage, ValueChangedHdl, weld::MetricSpinButton&, rEdit, void ) +{ + if (m_xRightMF->get() == &rEdit) + RightModify(); + ModifyHdl(rEdit); +} + +void SwFormatTablePage::ModifyHdl(const weld::MetricSpinButton& rEdit, bool bAllowInconsistencies) +{ + SwTwips nCurWidth = static_cast< SwTwips >(m_xWidthMF->DenormalizePercent(m_xWidthMF->get_value(FieldUnit::TWIP))); + SwTwips nPrevWidth = nCurWidth; + SwTwips nRight = static_cast< SwTwips >(m_xRightMF->DenormalizePercent(m_xRightMF->get_value(FieldUnit::TWIP))); + SwTwips nLeft = static_cast< SwTwips >(m_xLeftMF->DenormalizePercent(m_xLeftMF->get_value(FieldUnit::TWIP))); + SwTwips nDiff; + + if (&rEdit == m_xWidthMF->get()) + { + if( nCurWidth < MINLAY ) + nCurWidth = MINLAY; + nDiff = nRight + nLeft + nCurWidth - pTableData->GetSpace() ; + //right aligned: only change the left margin + if (m_xRightBtn->get_active()) + nLeft -= nDiff; + //left aligned: only change the right margin + else if(m_xLeftBtn->get_active()) + nRight -= nDiff; + //left margin and width allowed - first right - then left + else if (m_xFromLeftBtn->get_active()) + { + if( nRight >= nDiff ) + nRight -= nDiff; + else + { + nDiff -= nRight; + nRight = 0; + if(nLeft >= nDiff) + nLeft -= nDiff; + else + { + nRight += nLeft - nDiff; + nLeft = 0; + nCurWidth = pTableData->GetSpace(); + } + } + } + //centered: change both sides equally + else if (m_xCenterBtn->get_active()) + { + if(nLeft != nRight) + { + nDiff += nLeft + nRight; + nLeft = nDiff/2; + nRight = nDiff/2; + } + else + { + nLeft -= nDiff/2; + nRight -= nDiff/2; + } + } + //free alignment: decrease both margins + else if (m_xFreeBtn->get_active()) + { + nLeft -= nDiff/2; + nRight -= nDiff/2; + } + } + if (&rEdit == m_xRightMF->get()) + { + + if( nRight + nLeft > pTableData->GetSpace() - MINLAY ) + nRight = pTableData->GetSpace() -nLeft - MINLAY; + + nCurWidth = pTableData->GetSpace() - nLeft - nRight; + } + if (&rEdit == m_xLeftMF->get()) + { + if(!m_xFromLeftBtn->get_active()) + { + bool bCenter = m_xCenterBtn->get_active(); + if( bCenter ) + nRight = nLeft; + if(nRight + nLeft > pTableData->GetSpace() - MINLAY ) + { + nLeft = bCenter ? (pTableData->GetSpace() - MINLAY) /2 : + (pTableData->GetSpace() - MINLAY) - nRight; + nRight = bCenter ? (pTableData->GetSpace() - MINLAY) /2 : nRight; + } + nCurWidth = pTableData->GetSpace() - nLeft - nRight; + } + else + { + //Upon changes on the left side the right margin will be changed at first, + //thereafter the width. + nDiff = nRight + nLeft + nCurWidth - pTableData->GetSpace() ; + + nRight -= nDiff; + nCurWidth = pTableData->GetSpace() - nLeft - nRight; + } + } + + m_xRightMF->set_value( m_xRightMF->NormalizePercent( nRight ), FieldUnit::TWIP ); + m_xLeftMF->set_value( m_xLeftMF->NormalizePercent( nLeft ), FieldUnit::TWIP ); + + if (nCurWidth != nPrevWidth ) + { + m_xWidthMF->set_value(m_xWidthMF->NormalizePercent(nCurWidth), FieldUnit::TWIP); + + // tdf#135021 if the user changed the width spinbutton, and in this + // ModifyHdl we changed the value of that width spinbutton, then rerun + // the ModifyHdl on the replaced value so the left/right/width value + // relationships are consistent. + // But (tdf#135693) only make one effort of rectifying the inconsistency + if (&rEdit == m_xWidthMF->get() && !bAllowInconsistencies) + ModifyHdl(rEdit, true); + } + + bModified = true; +} + +std::unique_ptr<SfxTabPage> SwFormatTablePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique<SwFormatTablePage>(pPage, pController, *rAttrSet); +} + +bool SwFormatTablePage::FillItemSet( SfxItemSet* rCoreSet ) +{ + //Test if one of the controls still has the focus + if (m_xWidthMF->has_focus()) + ModifyHdl(*m_xWidthMF->get()); + else if (m_xLeftMF->has_focus()) + ModifyHdl(*m_xLeftMF->get()); + else if (m_xRightMF->has_focus()) + ModifyHdl(*m_xRightMF->get()); + else if (m_xTopMF->has_focus()) + ModifyHdl(*m_xTopMF); + else if (m_xBottomMF->has_focus()) + ModifyHdl(*m_xBottomMF); + + if (bModified) + { + if (m_xBottomMF->get_value_changed_from_saved() || + m_xTopMF->get_value_changed_from_saved() ) + { + SvxULSpaceItem aULSpace(RES_UL_SPACE); + aULSpace.SetUpper(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); + aULSpace.SetLower(m_xBottomMF->denormalize(m_xBottomMF->get_value(FieldUnit::TWIP))); + rCoreSet->Put(aULSpace); + } + + } + if (m_xNameED->get_value_changed_from_saved()) + { + rCoreSet->Put(SfxStringItem(FN_PARAM_TABLE_NAME, m_xNameED->get_text())); + bModified = true; + } + + if (m_xTextDirectionLB->get_visible()) + { + if (m_xTextDirectionLB->get_value_changed_from_saved()) + { + SvxFrameDirection nDirection = m_xTextDirectionLB->get_active_id(); + rCoreSet->Put(SvxFrameDirectionItem(nDirection, RES_FRAMEDIR)); + bModified = true; + } + } + + return bModified; +} + +void SwFormatTablePage::Reset( const SfxItemSet* ) +{ + const SfxItemSet& rSet = GetItemSet(); + + if(bHtmlMode) + { + m_xNameED->set_sensitive(false); + m_xTopFT->hide(); + m_xTopMF->hide(); + m_xBottomFT->hide(); + m_xBottomMF->hide(); + m_xFreeBtn->set_sensitive(false); + } + + // set back to original state + m_xRelWidthCB->set_active(false); + m_xWidthMF->ShowPercent(false); + m_xLeftMF->ShowPercent(false); + m_xRightMF->ShowPercent(false); + m_xWidthMF->SetMetricFieldRange(m_nOrigWidthMin, m_nOrigWidthMax); + m_xLeftMF->SetMetricFieldRange(m_nOrigLeftMin, m_nOrigLeftMax); + m_xRightMF->SetMetricFieldRange(m_nOrigRightMin, m_nOrigRightMax); + + FieldUnit aMetric = ::GetDfltMetric(bHtmlMode); + m_xWidthMF->SetMetric(aMetric); + m_xRightMF->SetMetric(aMetric); + m_xLeftMF->SetMetric(aMetric); + SetFieldUnit(*m_xTopMF, aMetric); + SetFieldUnit(*m_xBottomMF, aMetric); + + //Name + if(const SfxStringItem* pNameItem = rSet.GetItemIfSet( FN_PARAM_TABLE_NAME, false )) + { + m_xNameED->set_text(pNameItem->GetValue()); + m_xNameED->save_value(); + } + + if(const SwPtrItem* pRepItem = rSet.GetItemIfSet( FN_TABLE_REP, false )) + { + pTableData = static_cast<SwTableRep*>( pRepItem->GetValue()); + if (!m_xOrigTableData) + m_xOrigTableData.reset(new SwTableRep(*pTableData)); + else // tdf#134925 and tdf#134913, reset back to the original data seen on dialog creation + *pTableData = *m_xOrigTableData; + + nMinTableWidth = pTableData->GetColCount() * MINLAY; + + if(pTableData->GetWidthPercent()) + { + m_xRelWidthCB->set_active(true); + RelWidthClickHdl(*m_xRelWidthCB); + m_xWidthMF->set_value(pTableData->GetWidthPercent(), FieldUnit::PERCENT); + + m_xWidthMF->save_value(); + nSaveWidth = static_cast< SwTwips >(m_xWidthMF->get_value(FieldUnit::PERCENT)); + } + else + { + m_xWidthMF->set_value(m_xWidthMF->NormalizePercent( + pTableData->GetWidth()), FieldUnit::TWIP); + m_xWidthMF->save_value(); + nSaveWidth = pTableData->GetWidth(); + nMinTableWidth = std::min( nSaveWidth, nMinTableWidth ); + } + + m_xWidthMF->SetRefValue(pTableData->GetSpace()); + + m_xLeftMF->set_value(m_xLeftMF->NormalizePercent( + pTableData->GetLeftSpace()), FieldUnit::TWIP); + m_xRightMF->set_value(m_xRightMF->NormalizePercent( + pTableData->GetRightSpace()), FieldUnit::TWIP); + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + + bool bSetRight = false, bSetLeft = false; + switch( pTableData->GetAlign() ) + { + case text::HoriOrientation::NONE: + m_xFreeBtn->set_active(true); + if (m_xRelWidthCB->get_active()) + bSetRight = true; + break; + case text::HoriOrientation::FULL: + { + bSetRight = bSetLeft = true; + m_xFullBtn->set_active(true); + m_xWidthMF->set_sensitive(false); + m_xRelWidthCB->set_sensitive(false); + m_xWidthFT->set_sensitive(false); + } + break; + case text::HoriOrientation::LEFT: + { + bSetLeft = true; + m_xLeftBtn->set_active(true); + } + break; + case text::HoriOrientation::LEFT_AND_WIDTH : + { + bSetRight = true; + m_xFromLeftBtn->set_active(true); + } + break; + case text::HoriOrientation::RIGHT: + { + bSetRight = true; + m_xRightBtn->set_active(true); + } + break; + case text::HoriOrientation::CENTER: + { + bSetRight = true; + m_xCenterBtn->set_active(true); + } + break; + } + if ( bSetRight ) + { + m_xRightMF->set_sensitive(false); + m_xRightFT->set_sensitive(false); + } + if ( bSetLeft ) + { + m_xLeftMF->set_sensitive(false); + m_xLeftFT->set_sensitive(false); + } + + } + + //Margins + if(const SvxULSpaceItem* pSpaceItem = rSet.GetItemIfSet( RES_UL_SPACE, false )) + { + m_xTopMF->set_value(m_xTopMF->normalize( + pSpaceItem->GetUpper()), FieldUnit::TWIP); + m_xBottomMF->set_value(m_xBottomMF->normalize( + pSpaceItem->GetLower()), FieldUnit::TWIP); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + } + + //Text direction + if( const SvxFrameDirectionItem* pDirectionItem = rSet.GetItemIfSet( RES_FRAMEDIR ) ) + { + SvxFrameDirection nVal = pDirectionItem->GetValue(); + m_xTextDirectionLB->set_active_id(nVal); + m_xTextDirectionLB->save_value(); + } + + m_xWidthMF->set_max( 2*m_xWidthMF->NormalizePercent( pTableData->GetSpace() ), FieldUnit::TWIP ); + m_xRightMF->set_max( m_xRightMF->NormalizePercent( pTableData->GetSpace() ), FieldUnit::TWIP ); + m_xLeftMF->set_max( m_xLeftMF->NormalizePercent( pTableData->GetSpace() ), FieldUnit::TWIP ); + m_xWidthMF->set_min( m_xWidthMF->NormalizePercent( nMinTableWidth ), FieldUnit::TWIP ); +} + +void SwFormatTablePage::ActivatePage( const SfxItemSet& rSet ) +{ + OSL_ENSURE(pTableData, "table data not available?"); + if(SfxItemState::SET != rSet.GetItemState( FN_TABLE_REP )) + return; + + SwTwips nCurWidth = text::HoriOrientation::FULL != pTableData->GetAlign() ? + pTableData->GetWidth() : + pTableData->GetSpace(); + if(pTableData->GetWidthPercent() != 0 || + nCurWidth == m_xWidthMF->DenormalizePercent(m_xWidthMF->get_value(FieldUnit::TWIP))) + return; + + m_xWidthMF->set_value(m_xWidthMF->NormalizePercent( + nCurWidth), FieldUnit::TWIP); + m_xWidthMF->save_value(); + nSaveWidth = nCurWidth; + m_xLeftMF->set_value(m_xLeftMF->NormalizePercent( + pTableData->GetLeftSpace()), FieldUnit::TWIP); + m_xLeftMF->save_value(); + m_xRightMF->set_value(m_xRightMF->NormalizePercent( + pTableData->GetRightSpace()), FieldUnit::TWIP); + m_xRightMF->save_value(); +} + +DeactivateRC SwFormatTablePage::DeactivatePage( SfxItemSet* _pSet ) +{ + //test the table name for spaces + OUString sTableName = m_xNameED->get_text(); + if(sTableName.indexOf(' ') != -1) + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_WRONG_TABLENAME))); + xInfoBox->run(); + m_xNameED->grab_focus(); + return DeactivateRC::KeepPage; + } + if(_pSet) + { + FillItemSet(_pSet); + if(bModified) + { + SwTwips lLeft = static_cast< SwTwips >(m_xLeftMF->DenormalizePercent(m_xLeftMF->get_value(FieldUnit::TWIP))); + SwTwips lRight = static_cast< SwTwips >(m_xRightMF->DenormalizePercent(m_xRightMF->get_value(FieldUnit::TWIP))); + + if( m_xLeftMF->get_value_changed_from_saved() || + m_xRightMF->get_value_changed_from_saved() ) + { + pTableData->SetWidthChanged(); + pTableData->SetLeftSpace( lLeft); + pTableData->SetRightSpace( lRight); + } + + SwTwips lWidth; + if (m_xRelWidthCB->get_active() && m_xRelWidthCB->get_sensitive()) + { + lWidth = pTableData->GetSpace() - lRight - lLeft; + const sal_uInt16 nPercentWidth = m_xWidthMF->get_value(FieldUnit::PERCENT); + if(pTableData->GetWidthPercent() != nPercentWidth) + { + pTableData->SetWidthPercent(nPercentWidth); + pTableData->SetWidthChanged(); + } + } + else + { + pTableData->SetWidthPercent(0); + lWidth = static_cast<SwTwips>(m_xWidthMF->DenormalizePercent(m_xWidthMF->get_value(FieldUnit::TWIP))); + } + pTableData->SetWidth(lWidth); + + SwTwips nColSum = 0; + + for( sal_uInt16 i = 0; i < pTableData->GetColCount(); i++) + { + nColSum += pTableData->GetColumns()[i].nWidth; + } + if(nColSum != pTableData->GetWidth()) + { + SwTwips nMinWidth = std::min( tools::Long(MINLAY), + static_cast<tools::Long>(pTableData->GetWidth() / + pTableData->GetColCount() - 1)); + SwTwips nDiff = nColSum - pTableData->GetWidth(); + while ( std::abs(nDiff) > pTableData->GetColCount() + 1 ) + { + SwTwips nSub = nDiff / pTableData->GetColCount(); + for( sal_uInt16 i = 0; i < pTableData->GetColCount(); i++) + { + if(pTableData->GetColumns()[i].nWidth - nMinWidth > nSub) + { + pTableData->GetColumns()[i].nWidth -= nSub; + nDiff -= nSub; + } + else + { + nDiff -= pTableData->GetColumns()[i].nWidth - nMinWidth; + pTableData->GetColumns()[i].nWidth = nMinWidth; + } + + } + } + } + + sal_Int16 nAlign = 0; + if (m_xRightBtn->get_active()) + nAlign = text::HoriOrientation::RIGHT; + else if(m_xLeftBtn->get_active()) + nAlign = text::HoriOrientation::LEFT; + else if(m_xFromLeftBtn->get_active()) + nAlign = text::HoriOrientation::LEFT_AND_WIDTH; + else if(m_xCenterBtn->get_active()) + nAlign = text::HoriOrientation::CENTER; + else if(m_xFreeBtn->get_active()) + nAlign = text::HoriOrientation::NONE; + else if(m_xFullBtn->get_active()) + { + nAlign = text::HoriOrientation::FULL; + lWidth = lAutoWidth; + } + if(nAlign != pTableData->GetAlign()) + { + pTableData->SetWidthChanged(); + pTableData->SetAlign(nAlign); + } + + if(pTableData->GetWidth() != lWidth ) + { + pTableData->SetWidthChanged(); + pTableData->SetWidth( + nAlign == text::HoriOrientation::FULL ? pTableData->GetSpace() : lWidth ); + } + if(pTableData->HasWidthChanged()) + _pSet->Put(SwPtrItem(FN_TABLE_REP, pTableData)); + } + } + return DeactivateRC::LeavePage; +} + +//Description: Page column configuration +SwTableColumnPage::SwTableColumnPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/tablecolumnpage.ui", "TableColumnPage", &rSet) + , m_pTableData(nullptr) + , m_pSizeHdlEvent(nullptr) + , m_nTableWidth(0) + , m_nMinWidth(MINLAY) + , m_nMetFields(MET_FIELDS) + , m_nNoOfCols(0) + , m_nNoOfVisibleCols(0) + , m_bModified(false) + , m_bModifyTable(false) + , m_bPercentMode(false) + , m_aFieldArr { m_xBuilder->weld_metric_spin_button("width1", FieldUnit::CM), + m_xBuilder->weld_metric_spin_button("width2", FieldUnit::CM), + m_xBuilder->weld_metric_spin_button("width3", FieldUnit::CM), + m_xBuilder->weld_metric_spin_button("width4", FieldUnit::CM), + m_xBuilder->weld_metric_spin_button("width5", FieldUnit::CM)} + , m_aTextArr { m_xBuilder->weld_label("1"), + m_xBuilder->weld_label("2"), + m_xBuilder->weld_label("3"), + m_xBuilder->weld_label("4"), + m_xBuilder->weld_label("5")} + , m_xModifyTableCB(m_xBuilder->weld_check_button("adaptwidth")) + , m_xProportionalCB(m_xBuilder->weld_check_button("adaptcolumns")) + , m_xSpaceFT(m_xBuilder->weld_label("spaceft")) + , m_xSpaceSFT(m_xBuilder->weld_label("space")) + , m_xSpaceED(m_xBuilder->weld_metric_spin_button("spacefmt", FieldUnit::CM)) + , m_xUpBtn(m_xBuilder->weld_button("next")) + , m_xDownBtn(m_xBuilder->weld_button("back")) +{ + SetExchangeSupport(); + + // fire off this handler to happen on next event loop when all the rest of + // the pages are instantiated and the dialog preferred size is that of the + // all the pages that currently exist and the rest to come after this one + m_pSizeHdlEvent = Application::PostUserEvent(LINK(this, SwTableColumnPage, SizeHdl)); + + const SfxUInt16Item* pModeItem = GetItemSet().GetItemIfSet(SID_HTML_MODE, false); + Init(pModeItem && pModeItem->GetValue() & HTMLMODE_ON); +} + +IMPL_LINK_NOARG(SwTableColumnPage, SizeHdl, void*, void) +{ + m_pSizeHdlEvent = nullptr; + + //tdf#120420 keeping showing column width fields unless + //the dialog begins to grow, then stop adding them + weld::Window* pTopLevel = GetFrameWeld(); + Size aOrigSize = pTopLevel->get_preferred_size(); + for (sal_uInt16 i = 0; i < MET_FIELDS; ++i) + { + m_aFieldArr[i].show(); + m_aTextArr[i]->show(); + + if (pTopLevel->get_preferred_size().Width() > aOrigSize.Width()) + { + m_nMetFields = i + 1; + m_aTextArr[i]->set_grid_width(1); + m_xUpBtn->set_grid_left_attach(m_nMetFields * 2 - 1); + break; + } + } + + // tdf#143142 m_nMetFields has been updated and we need to re-check whether to show right button or not. + if (m_nNoOfVisibleCols > m_nMetFields) + { + m_xUpBtn->set_sensitive(true); + } + +} + +SwTableColumnPage::~SwTableColumnPage() +{ + if (m_pSizeHdlEvent) + { + Application::RemoveUserEvent(m_pSizeHdlEvent); + m_pSizeHdlEvent = nullptr; + } +} + +std::unique_ptr<SfxTabPage> SwTableColumnPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique<SwTableColumnPage>(pPage, pController, *rAttrSet); +} + +void SwTableColumnPage::Reset( const SfxItemSet* ) +{ + const SfxItemSet& rSet = GetItemSet(); + + if(const SwPtrItem* pRepItem = rSet.GetItemIfSet( FN_TABLE_REP, false )) + { + m_pTableData = static_cast<SwTableRep*>( pRepItem->GetValue()); + if (!m_xOrigTableData) + m_xOrigTableData.reset(new SwTableRep(*m_pTableData)); + else // tdf#134925 and tdf#134913, reset back to the original data seen on dialog creation + *m_pTableData = *m_xOrigTableData; + + m_nNoOfVisibleCols = m_pTableData->GetColCount(); + m_nNoOfCols = m_pTableData->GetAllColCount(); + m_nTableWidth = m_pTableData->GetAlign() != text::HoriOrientation::FULL && + m_pTableData->GetAlign() != text::HoriOrientation::LEFT_AND_WIDTH? + m_pTableData->GetWidth() : m_pTableData->GetSpace(); + + for( sal_uInt16 i = 0; i < m_nNoOfCols; i++ ) + { + if (m_pTableData->GetColumns()[i].nWidth < m_nMinWidth) + m_nMinWidth = m_pTableData->GetColumns()[i].nWidth; + } + sal_Int64 nMinTwips = m_aFieldArr[0].NormalizePercent( m_nMinWidth ); + sal_Int64 nMaxTwips = m_aFieldArr[0].NormalizePercent( m_nTableWidth ); + for( sal_uInt16 i = 0; (i < m_nMetFields) && (i < m_nNoOfVisibleCols); i++ ) + { + m_aFieldArr[i].set_value( m_aFieldArr[i].NormalizePercent( + GetVisibleWidth(i) ), FieldUnit::TWIP ); + m_aFieldArr[i].set_min(nMinTwips, FieldUnit::TWIP); + m_aFieldArr[i].set_max(nMaxTwips, FieldUnit::TWIP); + m_aFieldArr[i].set_sensitive(true); + m_aTextArr[i]->set_sensitive(true); + } + + if (m_nNoOfVisibleCols > m_nMetFields) + { + m_xUpBtn->set_sensitive(true); + } + + for( sal_uInt16 i = m_nNoOfVisibleCols; i < m_nMetFields; ++i ) + { + m_aFieldArr[i].set_text(OUString()); + m_aTextArr[i]->set_sensitive(false); + } + } + ActivatePage(rSet); +} + +void SwTableColumnPage::Init(bool bWeb) +{ + FieldUnit aMetric = ::GetDfltMetric(bWeb); + Link<weld::MetricSpinButton&,void> aLk = LINK(this, SwTableColumnPage, ValueChangedHdl); + for (sal_uInt16 i = 0; i < MET_FIELDS; ++i) + { + m_aValueTable[i] = i; + m_aFieldArr[i].SetMetric(aMetric); + m_aFieldArr[i].connect_value_changed(aLk); + } + SetFieldUnit(*m_xSpaceED, aMetric); + + Link<weld::Button&,void> aClickLk = LINK(this, SwTableColumnPage, AutoClickHdl); + m_xUpBtn->connect_clicked(aClickLk); + m_xDownBtn->connect_clicked(aClickLk); + + Link<weld::Toggleable&,void> aToggleLk = LINK(this, SwTableColumnPage, ModeHdl); + m_xModifyTableCB->connect_toggled(aToggleLk); + m_xProportionalCB->connect_toggled(aToggleLk); +} + +IMPL_LINK(SwTableColumnPage, AutoClickHdl, weld::Button&, rControl, void) +{ + //move display window + if (&rControl == m_xDownBtn.get()) + { + if(m_aValueTable[0] > 0) + { + for(sal_uInt16 & rn : m_aValueTable) + rn -= 1; + } + } + if (&rControl == m_xUpBtn.get()) + { + if( m_aValueTable[ m_nMetFields -1 ] < m_nNoOfVisibleCols -1 ) + { + for(sal_uInt16 & rn : m_aValueTable) + rn += 1; + } + } + for( sal_uInt16 i = 0; (i < m_nNoOfVisibleCols ) && ( i < m_nMetFields); i++ ) + { + OUString sEntry('~'); + OUString sIndex = OUString::number( m_aValueTable[i] + 1 ); + sEntry += sIndex; + m_aTextArr[i]->set_label(sEntry); + } + + m_xDownBtn->set_sensitive(m_aValueTable[0] > 0); + m_xUpBtn->set_sensitive(m_aValueTable[ m_nMetFields -1 ] < m_nNoOfVisibleCols -1 ); + UpdateCols(0); +} + +IMPL_LINK(SwTableColumnPage, ValueChangedHdl, weld::MetricSpinButton&, rEdit, void) +{ + m_bModified = true; + ModifyHdl(&rEdit); +} + +IMPL_LINK(SwTableColumnPage, ModeHdl, weld::Toggleable&, rBox, void) +{ + const bool bCheck = rBox.get_active(); + if (&rBox == m_xProportionalCB.get()) + { + if (bCheck) + m_xModifyTableCB->set_active(true); + m_xModifyTableCB->set_sensitive(!bCheck && m_bModifyTable); + } +} + +bool SwTableColumnPage::FillItemSet( SfxItemSet* ) +{ + for (SwPercentField & i : m_aFieldArr) + { + if (i.has_focus()) + { + ModifyHdl(i.get()); + break; + } + } + + if (m_bModified) + { + m_pTableData->SetColsChanged(); + } + return m_bModified; +} + +void SwTableColumnPage::ModifyHdl(const weld::MetricSpinButton* pField) +{ + SwPercentField *pEdit = nullptr; + sal_uInt16 i; + + for( i = 0; i < m_nMetFields; i++) + { + if (pField == m_aFieldArr[i].get()) + { + pEdit = &m_aFieldArr[i]; + break; + } + } + + if (m_nMetFields <= i || !pEdit) + { + OSL_ENSURE(false, "cannot happen."); + return; + } + + SetVisibleWidth(m_aValueTable[i], pEdit->DenormalizePercent(pEdit->get_value(FieldUnit::TWIP))); + + UpdateCols( m_aValueTable[i] ); +} + +void SwTableColumnPage::UpdateCols( sal_uInt16 nCurrentPos ) +{ + SwTwips nSum = 0; + + for( sal_uInt16 i = 0; i < m_nNoOfCols; i++ ) + { + nSum += (m_pTableData->GetColumns())[i].nWidth; + } + SwTwips nDiff = nSum - m_nTableWidth; + + bool bModifyTableChecked = m_xModifyTableCB->get_active(); + bool bProp = m_xProportionalCB->get_active(); + + if (!bModifyTableChecked && !bProp) + { + //The table width is constant, the difference is balanced with the other columns + sal_uInt16 nLoopCount = 0; + while( nDiff ) + { + if( ++nCurrentPos == m_nNoOfVisibleCols) + { + nCurrentPos = 0; + ++nLoopCount; + //#i101353# in small tables it might not be possible to balance column width + if( nLoopCount > 1 ) + break; + } + if( nDiff < 0 ) + { + SetVisibleWidth(nCurrentPos, GetVisibleWidth(nCurrentPos) -nDiff); + nDiff = 0; + } + else if( GetVisibleWidth(nCurrentPos) >= nDiff + m_nMinWidth ) + { + SetVisibleWidth(nCurrentPos, GetVisibleWidth(nCurrentPos) -nDiff); + nDiff = 0; + } + if( nDiff > 0 && GetVisibleWidth(nCurrentPos) > m_nMinWidth ) + { + if( nDiff >= (GetVisibleWidth(nCurrentPos) - m_nMinWidth) ) + { + nDiff -= (GetVisibleWidth(nCurrentPos) - m_nMinWidth); + SetVisibleWidth(nCurrentPos, m_nMinWidth); + } + else + { + nDiff = 0; + SetVisibleWidth(nCurrentPos, GetVisibleWidth(nCurrentPos) -nDiff); + } + OSL_ENSURE(nDiff >= 0, "nDiff < 0 cannot be here!"); + } + } + } + else if (bModifyTableChecked && !bProp) + { + //Difference is balanced by the width of the table, + //other columns remain unchanged. + OSL_ENSURE(nDiff <= m_pTableData->GetSpace() - m_nTableWidth, "wrong maximum" ); + SwTwips nActSpace = m_pTableData->GetSpace() - m_nTableWidth; + if(nDiff > nActSpace) + { + m_nTableWidth = m_pTableData->GetSpace(); + SetVisibleWidth(nCurrentPos, GetVisibleWidth(nCurrentPos) - nDiff + nActSpace ); + } + else + { + m_nTableWidth += nDiff; + } + } + else if (bModifyTableChecked && bProp) + { + //All columns will be changed proportionally with, + //the table width is adjusted accordingly. + const double fOrigColWidth = std::max(SwTwips(1), GetVisibleWidth(nCurrentPos) - nDiff); + const double fMaxWidth = std::max(m_pTableData->GetSpace(), m_nTableWidth); + const double fMaxPercent = fMaxWidth / m_nTableWidth; + const double fPercentChange = std::min(fMaxPercent, GetVisibleWidth(nCurrentPos)/fOrigColWidth); + SwTwips nNewTableSize = 0; + for( sal_uInt16 i = 0; i < m_nNoOfVisibleCols; i++ ) + { + SwTwips nNewColWidth = round( fPercentChange * (i == nCurrentPos ? fOrigColWidth : GetVisibleWidth(i)) ); + if ( nNewColWidth < MINLAY ) + nNewColWidth = MINLAY; + SetVisibleWidth(i, nNewColWidth); + nNewTableSize += nNewColWidth; + } + m_nTableWidth = nNewTableSize; + } + + if (!m_bPercentMode) + { + m_xSpaceED->set_value(m_xSpaceED->normalize(m_pTableData->GetSpace() - m_nTableWidth), FieldUnit::TWIP); + m_xSpaceSFT->set_label(m_xSpaceED->get_text()); + } + else + m_xSpaceSFT->set_label(OUString()); + + for( sal_uInt16 i = 0; ( i < m_nNoOfVisibleCols ) && ( i < m_nMetFields ); i++) + { + m_aFieldArr[i].set_value(m_aFieldArr[i].NormalizePercent( + GetVisibleWidth(m_aValueTable[i]) ), FieldUnit::TWIP); + } +} + +void SwTableColumnPage::ActivatePage( const SfxItemSet& ) +{ + m_bPercentMode = m_pTableData->GetWidthPercent() != 0; + for( sal_uInt16 i = 0; (i < m_nMetFields) && (i < m_nNoOfVisibleCols); i++ ) + { + m_aFieldArr[i].SetRefValue(m_pTableData->GetWidth()); + m_aFieldArr[i].ShowPercent( m_bPercentMode ); + } + + const sal_uInt16 nTableAlign = m_pTableData->GetAlign(); + if((text::HoriOrientation::FULL != nTableAlign && m_nTableWidth != m_pTableData->GetWidth()) || + (text::HoriOrientation::FULL == nTableAlign && m_nTableWidth != m_pTableData->GetSpace())) + { + m_nTableWidth = text::HoriOrientation::FULL == nTableAlign ? + m_pTableData->GetSpace() : + m_pTableData->GetWidth(); + UpdateCols(0); + } + m_bModifyTable = true; + if (m_pTableData->GetWidthPercent() || + text::HoriOrientation::FULL == nTableAlign || + m_pTableData->IsLineSelected() ) + m_bModifyTable = false; + if (m_bPercentMode) + { + m_xModifyTableCB->set_active(false); + m_xProportionalCB->set_active(false); + } + else if (!m_bModifyTable) + { + m_xProportionalCB->set_active(false); + m_xModifyTableCB->set_active(false); + } + m_xSpaceFT->set_sensitive(!m_bPercentMode); + m_xSpaceSFT->set_sensitive(!m_bPercentMode); + m_xModifyTableCB->set_sensitive( !m_bPercentMode && m_bModifyTable ); + m_xProportionalCB->set_sensitive(!m_bPercentMode && m_bModifyTable ); + + m_xSpaceED->set_value(m_xSpaceED->normalize( + m_pTableData->GetSpace() - m_nTableWidth), FieldUnit::TWIP); + m_xSpaceSFT->set_label(m_xSpaceED->get_text()); + +} + +DeactivateRC SwTableColumnPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if(_pSet) + { + FillItemSet(_pSet); + if(text::HoriOrientation::FULL != m_pTableData->GetAlign() && m_pTableData->GetWidth() != m_nTableWidth) + { + m_pTableData->SetWidth(m_nTableWidth); + SwTwips nDiff = m_pTableData->GetSpace() - m_pTableData->GetWidth() - + m_pTableData->GetLeftSpace() - m_pTableData->GetRightSpace(); + switch( m_pTableData->GetAlign() ) + { + case text::HoriOrientation::RIGHT: + m_pTableData->SetLeftSpace(m_pTableData->GetLeftSpace() + nDiff); + break; + case text::HoriOrientation::LEFT: + m_pTableData->SetRightSpace(m_pTableData->GetRightSpace() + nDiff); + break; + case text::HoriOrientation::NONE: + { + SwTwips nDiff2 = nDiff/2; + if( nDiff > 0 || + (-nDiff2 < m_pTableData->GetRightSpace() && - nDiff2 < m_pTableData->GetLeftSpace())) + { + m_pTableData->SetRightSpace(m_pTableData->GetRightSpace() + nDiff2); + m_pTableData->SetLeftSpace(m_pTableData->GetLeftSpace() + nDiff2); + } + else + { + if(m_pTableData->GetRightSpace() > m_pTableData->GetLeftSpace()) + { + m_pTableData->SetLeftSpace(0); + m_pTableData->SetRightSpace(m_pTableData->GetSpace() - m_pTableData->GetWidth()); + } + else + { + m_pTableData->SetRightSpace(0); + m_pTableData->SetLeftSpace(m_pTableData->GetSpace() - m_pTableData->GetWidth()); + } + } + } + break; + case text::HoriOrientation::CENTER: + m_pTableData->SetRightSpace(m_pTableData->GetRightSpace() + nDiff/2); + m_pTableData->SetLeftSpace(m_pTableData->GetLeftSpace() + nDiff/2); + break; + case text::HoriOrientation::LEFT_AND_WIDTH : + if(nDiff > m_pTableData->GetRightSpace()) + { + m_pTableData->SetLeftSpace(m_pTableData->GetSpace() - m_pTableData->GetWidth()); + } + m_pTableData->SetRightSpace( + m_pTableData->GetSpace() - m_pTableData->GetWidth() - m_pTableData->GetLeftSpace()); + break; + } + m_pTableData->SetWidthChanged(); + } + _pSet->Put(SwPtrItem( FN_TABLE_REP, m_pTableData )); + } + return DeactivateRC::LeavePage; +} + +SwTwips SwTableColumnPage::GetVisibleWidth(sal_uInt16 nPos) +{ + sal_uInt16 i=0; + + while( nPos ) + { + if(m_pTableData->GetColumns()[i].bVisible) + nPos--; + i++; + } + SwTwips nReturn = m_pTableData->GetColumns()[i].nWidth; + OSL_ENSURE(i < m_nNoOfCols, "Array index out of range"); + while(!m_pTableData->GetColumns()[i].bVisible && (i + 1) < m_nNoOfCols) + nReturn += m_pTableData->GetColumns()[++i].nWidth; + + return nReturn; +} + +void SwTableColumnPage::SetVisibleWidth(sal_uInt16 nPos, SwTwips nNewWidth) +{ + sal_uInt16 i=0; + while( nPos ) + { + if(m_pTableData->GetColumns()[i].bVisible) + nPos--; + i++; + } + OSL_ENSURE(i < m_nNoOfCols, "Array index out of range"); + m_pTableData->GetColumns()[i].nWidth = nNewWidth; + while(!m_pTableData->GetColumns()[i].bVisible && (i + 1) < m_nNoOfCols) + m_pTableData->GetColumns()[++i].nWidth = 0; + +} + +SwTableTabDlg::SwTableTabDlg(weld::Window* pParent, const SfxItemSet* pItemSet, SwWrtShell* pSh) + : SfxTabDialogController(pParent, "modules/swriter/ui/tableproperties.ui", "TablePropertiesDialog", pItemSet) + , pShell(pSh) +{ + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + AddTabPage("table", &SwFormatTablePage::Create, nullptr); + AddTabPage("textflow", &SwTextFlowPage::Create, nullptr); + AddTabPage("columns", &SwTableColumnPage::Create, nullptr); + AddTabPage("background", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BKG), nullptr); + AddTabPage("borders", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BORDER), nullptr); +} + +void SwTableTabDlg::PageCreated(const OString& rId, SfxTabPage& rPage) +{ + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + if (rId == "background") + { + SvxBackgroundTabFlags const nFlagType = SvxBackgroundTabFlags::SHOW_TBLCTL; + aSet.Put (SfxUInt32Item(SID_FLAG_TYPE, static_cast<sal_uInt32>(nFlagType))); + rPage.PageCreated(aSet); + } + else if (rId == "borders") + { + aSet.Put (SfxUInt16Item(SID_SWMODE_TYPE, static_cast<sal_uInt16>(SwBorderModes::TABLE))); + rPage.PageCreated(aSet); + } + else if (rId == "textflow") + { + static_cast<SwTextFlowPage&>(rPage).SetShell(pShell); + const FrameTypeFlags eType = pShell->GetFrameType(nullptr,true); + if( !(FrameTypeFlags::BODY & eType) ) + static_cast<SwTextFlowPage&>(rPage).DisablePageBreak(); + } +} + +SwTextFlowPage::SwTextFlowPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/tabletextflowpage.ui", "TableTextFlowPage", &rSet) + , pShell(nullptr) + , bPageBreak(true) + , bHtmlMode(false) + , m_xPgBrkCB(m_xBuilder->weld_check_button("break")) + , m_xPgBrkRB(m_xBuilder->weld_radio_button("page")) + , m_xColBrkRB(m_xBuilder->weld_radio_button("column")) + , m_xPgBrkBeforeRB(m_xBuilder->weld_radio_button("before")) + , m_xPgBrkAfterRB(m_xBuilder->weld_radio_button("after")) + , m_xPageCollCB(m_xBuilder->weld_check_button("pagestyle")) + , m_xPageCollLB(m_xBuilder->weld_combo_box("pagestylelb")) + , m_xPageNoCB(m_xBuilder->weld_check_button("pagenoft")) + , m_xPageNoNF(m_xBuilder->weld_spin_button("pagenonf")) + , m_xSplitCB(m_xBuilder->weld_check_button("split")) + , m_xSplitRowCB(m_xBuilder->weld_check_button("splitrow")) + , m_xKeepCB(m_xBuilder->weld_check_button("keep")) + , m_xHeadLineCB(m_xBuilder->weld_check_button("headline")) + , m_xRepeatHeaderCombo(m_xBuilder->weld_widget("repeatheader")) + , m_xRepeatHeaderNF(m_xBuilder->weld_spin_button("repeatheadernf")) + , m_xTextDirectionLB(m_xBuilder->weld_combo_box("textorientation")) + , m_xVertOrientLB(m_xBuilder->weld_combo_box("vertorient")) +{ + m_xPgBrkCB->connect_toggled(LINK(this, SwTextFlowPage, PageBreakHdl_Impl)); + m_xPgBrkBeforeRB->connect_toggled( + LINK(this, SwTextFlowPage, PageBreakPosHdl_Impl)); + m_xPgBrkAfterRB->connect_toggled( + LINK(this, SwTextFlowPage, PageBreakPosHdl_Impl)); + m_xPageCollCB->connect_toggled( + LINK(this, SwTextFlowPage, ApplyCollClickHdl_Impl)); + m_xColBrkRB->connect_toggled( + LINK(this, SwTextFlowPage, PageBreakTypeHdl_Impl)); + m_xPgBrkRB->connect_toggled( + LINK(this, SwTextFlowPage, PageBreakTypeHdl_Impl)); + m_xPageNoCB->connect_toggled( + LINK(this, SwTextFlowPage, PageNoClickHdl_Impl)); + m_xSplitCB->connect_toggled( + LINK(this, SwTextFlowPage, SplitHdl_Impl)); + m_xHeadLineCB->connect_toggled(LINK(this, SwTextFlowPage, HeadLineCBClickHdl)); + + const SfxUInt16Item *pModeItem = rSet.GetItemIfSet( SID_HTML_MODE, false ); + if(pModeItem && pModeItem->GetValue() & HTMLMODE_ON) + { + m_xKeepCB->hide(); + m_xSplitCB->hide(); + m_xSplitRowCB->hide(); + } + + HeadLineCBClickHdl(*m_xHeadLineCB); +} + +SwTextFlowPage::~SwTextFlowPage() +{ +} + +std::unique_ptr<SfxTabPage> SwTextFlowPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SwTextFlowPage>(pPage, pController, *rAttrSet); +} + +bool SwTextFlowPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + + //Repeat Heading + if (m_xHeadLineCB->get_state_changed_from_saved() || + m_xRepeatHeaderNF->get_value_changed_from_saved() ) + { + bModified |= nullptr != rSet->Put( + SfxUInt16Item(FN_PARAM_TABLE_HEADLINE, m_xHeadLineCB->get_active() ? sal_uInt16(m_xRepeatHeaderNF->get_value()) : 0)); + } + if (m_xKeepCB->get_state_changed_from_saved()) + bModified |= nullptr != rSet->Put( SvxFormatKeepItem( m_xKeepCB->get_active(), RES_KEEP)); + + if (m_xSplitCB->get_state_changed_from_saved()) + bModified |= nullptr != rSet->Put( SwFormatLayoutSplit( m_xSplitCB->get_active())); + + if (m_xSplitRowCB->get_state_changed_from_saved()) + bModified |= nullptr != rSet->Put( SwFormatRowSplit( m_xSplitRowCB->get_active())); + + const SvxFormatBreakItem* pBreak = GetOldItem( *rSet, RES_BREAK ); + const SwFormatPageDesc* pDesc = GetOldItem( *rSet, RES_PAGEDESC ); + + bool bState = m_xPageCollCB->get_active(); + + //If we have a page style, then there's no break + bool bPageItemPut = false; + if ( bState != (m_xPageCollCB->get_saved_state() == TRISTATE_TRUE) + || (bState && m_xPageCollLB->get_value_changed_from_saved()) + || (m_xPageNoCB->get_sensitive() && m_xPageNoCB->get_state_changed_from_saved()) + || (m_xPageNoNF->get_sensitive() && m_xPageNoNF->get_value_changed_from_saved())) + { + OUString sPage; + + if ( bState ) + { + sPage = m_xPageCollLB->get_active_text(); + } + sal_uInt16 nPgNum = o3tl::narrowing<sal_uInt16>(m_xPageNoNF->get_value()); + bool const usePageNo(bState && m_xPageNoCB->get_active()); + std::optional<sal_uInt16> const oPageNum( + usePageNo ? nPgNum : std::optional<sal_Int16>()); + if (!pDesc || !pDesc->GetPageDesc() + || (pDesc->GetPageDesc()->GetName() != sPage) + || (pDesc->GetNumOffset() != oPageNum)) + { + SwFormatPageDesc aFormat( pShell->FindPageDescByName( sPage, true ) ); + aFormat.SetNumOffset(oPageNum); + bModified |= nullptr != rSet->Put( aFormat ); + bPageItemPut = bState; + } + } + bool bIsChecked = m_xPgBrkCB->get_active(); + if ( !bPageItemPut && + ( bState != (m_xPageCollCB->get_saved_state() == TRISTATE_TRUE) || + bIsChecked != (m_xPgBrkCB->get_saved_state() == TRISTATE_TRUE) || + m_xPgBrkBeforeRB->get_state_changed_from_saved() || + m_xPgBrkRB->get_state_changed_from_saved() )) + { + SvxFormatBreakItem aBreak( GetItemSet().Get( RES_BREAK ) ); + + if(bIsChecked) + { + bool bBefore = m_xPgBrkBeforeRB->get_active(); + + if (m_xPgBrkRB->get_active()) + { + if ( bBefore ) + aBreak.SetValue( SvxBreak::PageBefore ); + else + aBreak.SetValue( SvxBreak::PageAfter ); + } + else + { + if ( bBefore ) + aBreak.SetValue( SvxBreak::ColumnBefore ); + else + aBreak.SetValue( SvxBreak::ColumnAfter ); + } + } + else + { + aBreak.SetValue( SvxBreak::NONE ); + } + + if ( !pBreak || !( *pBreak == aBreak ) ) + { + bModified |= nullptr != rSet->Put( aBreak ); + } + } + + if (m_xTextDirectionLB->get_value_changed_from_saved()) + { + OUString sId = m_xTextDirectionLB->get_active_id(); + bModified |= nullptr != rSet->Put(SvxFrameDirectionItem(static_cast<SvxFrameDirection>(sId.toUInt32()), FN_TABLE_BOX_TEXTORIENTATION)); + } + + if (m_xVertOrientLB->get_value_changed_from_saved()) + { + sal_uInt16 nOrient = USHRT_MAX; + switch (m_xVertOrientLB->get_active()) + { + case 0 : nOrient = text::VertOrientation::NONE; break; + case 1 : nOrient = text::VertOrientation::CENTER; break; + case 2 : nOrient = text::VertOrientation::BOTTOM; break; + } + if (nOrient != USHRT_MAX) + bModified |= nullptr != rSet->Put(SfxUInt16Item(FN_TABLE_SET_VERT_ALIGN, nOrient)); + } + + return bModified; + +} + +void SwTextFlowPage::Reset( const SfxItemSet* rSet ) +{ + bool bFlowAllowed = !bHtmlMode || SvxHtmlOptions::IsPrintLayoutExtension(); + if(bFlowAllowed) + { + //Inserting of the existing page templates in the list box + const size_t nCount = pShell->GetPageDescCnt(); + + for( size_t i = 0; i < nCount; ++i) + { + const SwPageDesc &rPageDesc = pShell->GetPageDesc(i); + m_xPageCollLB->append_text(rPageDesc.GetName()); + } + + OUString aFormatName; + for (sal_uInt16 i = RES_POOLPAGE_BEGIN; i < RES_POOLPAGE_END; ++i) + { + aFormatName = SwStyleNameMapper::GetUIName(i, aFormatName); + if (m_xPageCollLB->find_text(aFormatName) == -1) + m_xPageCollLB->append_text(aFormatName); + } + + if(const SvxFormatKeepItem* pKeepItem = rSet->GetItemIfSet( RES_KEEP, false )) + { + m_xKeepCB->set_active( pKeepItem->GetValue() ); + m_xKeepCB->save_state(); + } + if(const SwFormatLayoutSplit* pSplitItem = rSet->GetItemIfSet( RES_LAYOUT_SPLIT, false )) + { + m_xSplitCB->set_active( pSplitItem->GetValue() ); + } + else + m_xSplitCB->set_active(true); + + m_xSplitCB->save_state(); + SplitHdl_Impl(*m_xSplitCB); + + if(const SwFormatRowSplit* pSplitItem = rSet->GetItemIfSet( RES_ROW_SPLIT, false )) + { + m_xSplitRowCB->set_active( pSplitItem->GetValue() ); + } + else + m_xSplitRowCB->set_state(TRISTATE_INDET); + m_xSplitRowCB->save_state(); + + if(bPageBreak) + { + if(const SwFormatPageDesc* pPageDescItem = rSet->GetItemIfSet( RES_PAGEDESC, false )) + { + OUString sPageDesc; + const SwPageDesc* pDesc = pPageDescItem->GetPageDesc(); + + ::std::optional<sal_uInt16> oNumOffset = pPageDescItem->GetNumOffset(); + if (oNumOffset) + { + m_xPageNoCB->set_active(true); + m_xPageNoNF->set_sensitive(true); + m_xPageNoNF->set_value(*oNumOffset); + } + else + { + m_xPageNoCB->set_active(false); + m_xPageNoNF->set_sensitive(false); + } + + if(pDesc) + sPageDesc = pDesc->GetName(); + if (!sPageDesc.isEmpty() && m_xPageCollLB->find_text(sPageDesc) != -1) + { + m_xPageCollLB->set_active_text(sPageDesc); + m_xPageCollCB->set_active(true); + + m_xPgBrkCB->set_sensitive(true); + m_xPgBrkRB->set_sensitive(true); + m_xColBrkRB->set_sensitive(true); + m_xPgBrkBeforeRB->set_sensitive(true); + m_xPgBrkAfterRB->set_sensitive(true); + m_xPageCollCB->set_sensitive(true); + + m_xPgBrkCB->set_active(true); + m_xColBrkRB->set_active( false ); + m_xPgBrkBeforeRB->set_active(true); + m_xPgBrkAfterRB->set_active( false ); + } + else + { + m_xPageCollLB->set_active(-1); + m_xPageCollCB->set_active(false); + } + } + + if(const SvxFormatBreakItem* pPageBreak = rSet->GetItemIfSet( RES_BREAK, false )) + { + SvxBreak eBreak = pPageBreak->GetBreak(); + + if ( eBreak != SvxBreak::NONE ) + { + m_xPgBrkCB->set_active(true); + m_xPageCollCB->set_sensitive(false); + m_xPageCollLB->set_sensitive(false); + m_xPageNoCB->set_sensitive(false); + m_xPageNoNF->set_sensitive(false); + } + switch ( eBreak ) + { + case SvxBreak::PageBefore: + m_xPgBrkRB->set_active(true); + m_xColBrkRB->set_active( false ); + m_xPgBrkBeforeRB->set_active(true); + m_xPgBrkAfterRB->set_active( false ); + break; + case SvxBreak::PageAfter: + m_xPgBrkRB->set_active(true); + m_xColBrkRB->set_active( false ); + m_xPgBrkBeforeRB->set_active( false ); + m_xPgBrkAfterRB->set_active(true); + break; + case SvxBreak::ColumnBefore: + m_xPgBrkRB->set_active( false ); + m_xColBrkRB->set_active(true); + m_xPgBrkBeforeRB->set_active(true); + m_xPgBrkAfterRB->set_active( false ); + break; + case SvxBreak::ColumnAfter: + m_xPgBrkRB->set_active( false ); + m_xColBrkRB->set_active(true); + m_xPgBrkBeforeRB->set_active( false ); + m_xPgBrkAfterRB->set_active(true); + break; + default:; //prevent warning + } + + } + if (m_xPgBrkBeforeRB->get_active()) + PageBreakPosHdl_Impl(*m_xPgBrkBeforeRB); + else if (m_xPgBrkAfterRB->get_active()) + PageBreakPosHdl_Impl(*m_xPgBrkAfterRB); + PageBreakHdl_Impl(*m_xPgBrkCB); + } + } + else + { + m_xPgBrkRB->set_sensitive(false); + m_xColBrkRB->set_sensitive(false); + m_xPgBrkBeforeRB->set_sensitive(false); + m_xPgBrkAfterRB->set_sensitive(false); + m_xKeepCB->set_sensitive(false); + m_xSplitCB->set_sensitive(false); + m_xPgBrkCB->set_sensitive(false); + m_xPageCollCB->set_sensitive(false); + m_xPageCollLB->set_sensitive(false); + } + + if(const SfxUInt16Item* pHeadlineItem = rSet->GetItemIfSet( FN_PARAM_TABLE_HEADLINE, false )) + { + sal_uInt16 nRep = pHeadlineItem->GetValue(); + m_xHeadLineCB->set_active(nRep > 0); + m_xHeadLineCB->save_state(); + m_xRepeatHeaderNF->set_value(nRep); + m_xRepeatHeaderNF->set_min(1); + m_xRepeatHeaderNF->save_value(); + } + if ( rSet->GetItemState(FN_TABLE_BOX_TEXTORIENTATION) > SfxItemState::DEFAULT ) + { + SvxFrameDirection nDirection = rSet->Get(FN_TABLE_BOX_TEXTORIENTATION).GetValue(); + m_xTextDirectionLB->set_active_id(OUString::number(static_cast<sal_uInt32>(nDirection))); + } + + if ( rSet->GetItemState(FN_TABLE_SET_VERT_ALIGN) > SfxItemState::DEFAULT ) + { + sal_uInt16 nVert = rSet->Get(FN_TABLE_SET_VERT_ALIGN).GetValue(); + sal_uInt16 nPos = 0; + switch(nVert) + { + case text::VertOrientation::NONE: nPos = 0; break; + case text::VertOrientation::CENTER: nPos = 1; break; + case text::VertOrientation::BOTTOM: nPos = 2; break; + } + m_xVertOrientLB->set_active(nPos); + } + + m_xPageCollCB->save_state(); + m_xPageCollLB->save_value(); + m_xPgBrkCB->save_state(); + m_xPgBrkRB->save_state(); + m_xColBrkRB->save_state(); + m_xPgBrkBeforeRB->save_state(); + m_xPgBrkAfterRB->save_state(); + m_xPageNoCB->save_state(); + m_xPageNoNF->save_value(); + m_xTextDirectionLB->save_value(); + m_xVertOrientLB->save_value(); + + HeadLineCBClickHdl(*m_xHeadLineCB); +} + +void SwTextFlowPage::SetShell(SwWrtShell* pSh) +{ + pShell = pSh; + bHtmlMode = 0 != (::GetHtmlMode(pShell->GetView().GetDocShell()) & HTMLMODE_ON); + if(bHtmlMode) + { + m_xPageNoNF->set_sensitive(false); + m_xPageNoCB->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SwTextFlowPage, PageBreakHdl_Impl, weld::Toggleable&, void) +{ + if (m_xPgBrkCB->get_active()) + { + m_xPgBrkRB->set_sensitive(true); + m_xColBrkRB->set_sensitive(true); + m_xPgBrkBeforeRB->set_sensitive(true); + m_xPgBrkAfterRB->set_sensitive(true); + + if (m_xPgBrkRB->get_active() && m_xPgBrkBeforeRB->get_active()) + { + m_xPageCollCB->set_sensitive(true); + + bool bEnable = m_xPageCollCB->get_active() && m_xPageCollLB->get_count(); + m_xPageCollLB->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNoCB->set_sensitive(bEnable); + m_xPageNoNF->set_sensitive(bEnable && m_xPageNoCB->get_active()); + } + } + } + else + { + m_xPageCollCB->set_active(false); + m_xPageCollCB->set_sensitive(false); + m_xPageCollLB->set_sensitive(false); + m_xPageNoCB->set_sensitive(false); + m_xPageNoNF->set_sensitive(false); + m_xPgBrkRB->set_sensitive(false); + m_xColBrkRB->set_sensitive(false); + m_xPgBrkBeforeRB->set_sensitive(false); + m_xPgBrkAfterRB->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SwTextFlowPage, ApplyCollClickHdl_Impl, weld::Toggleable&, void) +{ + bool bEnable = false; + if (m_xPageCollCB->get_active() && m_xPageCollLB->get_count()) + { + bEnable = true; + m_xPageCollLB->set_active(0); + } + else + { + m_xPageCollLB->set_active(-1); + } + m_xPageCollLB->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNoCB->set_sensitive(bEnable); + m_xPageNoNF->set_sensitive(bEnable && m_xPageNoCB->get_active()); + } +} + +IMPL_LINK_NOARG(SwTextFlowPage, PageBreakPosHdl_Impl, weld::Toggleable&, void) +{ + if (!m_xPgBrkCB->get_active()) + return; + + if (m_xPgBrkBeforeRB->get_active() && m_xPgBrkRB->get_active()) + { + m_xPageCollCB->set_sensitive(true); + + bool bEnable = m_xPageCollCB->get_active() && m_xPageCollLB->get_count(); + + m_xPageCollLB->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNoCB->set_sensitive(bEnable); + m_xPageNoNF->set_sensitive(bEnable && m_xPageNoCB->get_active()); + } + } + else if (m_xPgBrkAfterRB->get_active()) + { + m_xPageCollCB->set_active(false); + m_xPageCollCB->set_sensitive(false); + m_xPageCollLB->set_sensitive(false); + m_xPageNoCB->set_sensitive(false); + m_xPageNoNF->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SwTextFlowPage, PageBreakTypeHdl_Impl, weld::Toggleable&, void) +{ + if (m_xColBrkRB->get_active() || m_xPgBrkAfterRB->get_active()) + { + m_xPageCollCB->set_active(false); + m_xPageCollCB->set_sensitive(false); + m_xPageCollLB->set_sensitive(false); + m_xPageNoCB->set_sensitive(false); + m_xPageNoNF->set_sensitive(false); + } + else if (m_xPgBrkBeforeRB->get_active()) + PageBreakPosHdl_Impl(*m_xPgBrkBeforeRB); +} + +IMPL_LINK_NOARG(SwTextFlowPage, PageNoClickHdl_Impl, weld::Toggleable&, void) +{ + m_xPageNoNF->set_sensitive(m_xPageNoCB->get_active()); +} + +IMPL_LINK(SwTextFlowPage, SplitHdl_Impl, weld::Toggleable&, rBox, void) +{ + m_xSplitRowCB->set_sensitive(rBox.get_active()); +} + +IMPL_LINK_NOARG(SwTextFlowPage, HeadLineCBClickHdl, weld::Toggleable&, void) +{ + m_xRepeatHeaderCombo->set_sensitive(m_xHeadLineCB->get_active()); +} + +void SwTextFlowPage::DisablePageBreak() +{ + bPageBreak = false; + m_xPgBrkCB->set_sensitive(false); + m_xPgBrkRB->set_sensitive(false); + m_xColBrkRB->set_sensitive(false); + m_xPgBrkBeforeRB->set_sensitive(false); + m_xPgBrkAfterRB->set_sensitive(false); + m_xPageCollCB->set_sensitive(false); + m_xPageCollLB->set_sensitive(false); + m_xPageNoCB->set_sensitive(false); + m_xPageNoNF->set_sensitive(false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/table/tautofmt.cxx b/sw/source/ui/table/tautofmt.cxx new file mode 100644 index 000000000..8dbc965e8 --- /dev/null +++ b/sw/source/ui/table/tautofmt.cxx @@ -0,0 +1,408 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sal/log.hxx> +#include <strings.hrc> +#include <shellres.hxx> +#include <tautofmt.hxx> + +namespace { + +class SwStringInputDlg : public SfxDialogController +{ +private: + std::unique_ptr<weld::Label> m_xLabel; + std::unique_ptr<weld::Entry> m_xEdInput; // Edit obtains the focus. + +public: + SwStringInputDlg(weld::Window* pParent, const OUString& rTitle, + const OUString& rEditTitle, const OUString& rDefault) + : SfxDialogController(pParent, "modules/swriter/ui/stringinput.ui", + "StringInputDialog") + , m_xLabel(m_xBuilder->weld_label("name")) + , m_xEdInput(m_xBuilder->weld_entry("edit")) + { + m_xLabel->set_label(rEditTitle); + m_xDialog->set_title(rTitle); + m_xEdInput->set_text(rDefault); + m_xEdInput->select_region(0, -1); + } + + OUString GetInputString() const + { + return m_xEdInput->get_text(); + } +}; + +} + +// AutoFormat-Dialogue: +SwAutoFormatDlg::SwAutoFormatDlg(weld::Window* pParent, SwWrtShell* pWrtShell, + bool bAutoFormat, const SwTableAutoFormat* pSelFormat) + : SfxDialogController(pParent, "modules/swriter/ui/autoformattable.ui", + "AutoFormatTableDialog") + , m_aStrTitle(SwResId(STR_ADD_AUTOFORMAT_TITLE)) + , m_aStrLabel(SwResId(STR_ADD_AUTOFORMAT_LABEL)) + , m_aStrClose(SwResId(STR_BTN_AUTOFORMAT_CLOSE)) + , m_aStrDelTitle(SwResId(STR_DEL_AUTOFORMAT_TITLE)) + , m_aStrDelMsg(SwResId(STR_DEL_AUTOFORMAT_MSG)) + , m_aStrRenameTitle(SwResId(STR_RENAME_AUTOFORMAT_TITLE)) + , m_aStrInvalidFormat(SwResId(STR_INVALID_AUTOFORMAT_NAME)) + , m_pShell(pWrtShell) + , m_nIndex(0) + , m_nDfltStylePos(0) + , m_bCoreDataChanged(false) + , m_bSetAutoFormat(bAutoFormat) + , m_xTableTable(new SwTableAutoFormatTable) + , m_xLbFormat(m_xBuilder->weld_tree_view("formatlb")) + , m_xBtnNumFormat(m_xBuilder->weld_check_button("numformatcb")) + , m_xBtnBorder(m_xBuilder->weld_check_button("bordercb")) + , m_xBtnFont(m_xBuilder->weld_check_button("fontcb")) + , m_xBtnPattern(m_xBuilder->weld_check_button("patterncb")) + , m_xBtnAlignment(m_xBuilder->weld_check_button("alignmentcb")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnRemove(m_xBuilder->weld_button("remove")) + , m_xBtnRename(m_xBuilder->weld_button("rename")) + , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aWndPreview)) +{ + m_aWndPreview.DetectRTL(pWrtShell); + m_xTableTable->Load(); + + const int nWidth = m_xLbFormat->get_approximate_digit_width() * 32; + const int nHeight = m_xLbFormat->get_height_rows(8); + m_xLbFormat->set_size_request(nWidth, nHeight); + m_xWndPreview->set_size_request(nWidth, nHeight); + + Init(pSelFormat); +} + +SwAutoFormatDlg::~SwAutoFormatDlg() +{ + try + { + if (m_bCoreDataChanged) + m_xTableTable->Save(); + } + catch (...) + { + } + m_xTableTable.reset(); +} + +void SwAutoFormatDlg::Init( const SwTableAutoFormat* pSelFormat ) +{ + Link<weld::Toggleable&, void> aLk(LINK(this, SwAutoFormatDlg, CheckHdl)); + m_xBtnBorder->connect_toggled(aLk); + m_xBtnFont->connect_toggled(aLk); + m_xBtnPattern->connect_toggled(aLk); + m_xBtnAlignment->connect_toggled(aLk); + m_xBtnNumFormat->connect_toggled(aLk); + + m_xBtnAdd->connect_clicked(LINK(this, SwAutoFormatDlg, AddHdl)); + m_xBtnRemove->connect_clicked(LINK(this, SwAutoFormatDlg, RemoveHdl)); + m_xBtnRename->connect_clicked(LINK(this, SwAutoFormatDlg, RenameHdl)); + m_xLbFormat->connect_changed(LINK(this, SwAutoFormatDlg, SelFormatHdl)); + + m_xBtnAdd->set_sensitive(m_bSetAutoFormat); + + m_nIndex = 0; + if( !m_bSetAutoFormat ) + { + // Then the list to be expanded by the entry "- none -". + m_xLbFormat->append_text(SwViewShell::GetShellRes()->aStrNone); + m_nDfltStylePos = 1; + m_nIndex = 255; + } + + for (sal_uInt8 i = 0, nCount = static_cast<sal_uInt8>(m_xTableTable->size()); + i < nCount; i++) + { + SwTableAutoFormat const& rFormat = (*m_xTableTable)[ i ]; + m_xLbFormat->append_text(rFormat.GetName()); + if (pSelFormat && rFormat.GetName() == pSelFormat->GetName()) + m_nIndex = i; + } + + m_xLbFormat->select(255 != m_nIndex ? (m_nDfltStylePos + m_nIndex) : 0); + SelFormatHdl(*m_xLbFormat); +} + +void SwAutoFormatDlg::UpdateChecks( const SwTableAutoFormat& rFormat, bool bEnable ) +{ + m_xBtnNumFormat->set_sensitive(bEnable); + m_xBtnNumFormat->set_active(rFormat.IsValueFormat()); + + m_xBtnBorder->set_sensitive(bEnable); + m_xBtnBorder->set_active(rFormat.IsFrame()); + + m_xBtnFont->set_sensitive(bEnable); + m_xBtnFont->set_active(rFormat.IsFont()); + + m_xBtnPattern->set_sensitive(bEnable); + m_xBtnPattern->set_active(rFormat.IsBackground()); + + m_xBtnAlignment->set_sensitive(bEnable); + m_xBtnAlignment->set_active(rFormat.IsJustify()); +} + +std::unique_ptr<SwTableAutoFormat> SwAutoFormatDlg::FillAutoFormatOfIndex() const +{ + if( 255 != m_nIndex ) + { + return std::make_unique<SwTableAutoFormat>( (*m_xTableTable)[ m_nIndex ] ); + } + + return nullptr; +} + +// Handler: +IMPL_LINK(SwAutoFormatDlg, CheckHdl, weld::Toggleable&, rBtn, void) +{ + if (m_nIndex == 255) + return; + + SwTableAutoFormat& rData = (*m_xTableTable)[m_nIndex]; + bool bCheck = rBtn.get_active(), bDataChgd = true; + + if (&rBtn == m_xBtnNumFormat.get()) + rData.SetValueFormat( bCheck ); + else if (&rBtn == m_xBtnBorder.get()) + rData.SetFrame( bCheck ); + else if (&rBtn == m_xBtnFont.get()) + rData.SetFont( bCheck ); + else if (&rBtn == m_xBtnPattern.get()) + rData.SetBackground( bCheck ); + else if (&rBtn == m_xBtnAlignment.get()) + rData.SetJustify( bCheck ); + else + bDataChgd = false; + + if( bDataChgd ) + { + if( !m_bCoreDataChanged ) + { + m_xBtnCancel->set_label(m_aStrClose); + m_bCoreDataChanged = true; + } + + m_aWndPreview.NotifyChange(rData); + } +} + +IMPL_LINK_NOARG(SwAutoFormatDlg, AddHdl, weld::Button&, void) +{ + bool bOk = false, bFormatInserted = false; + while( !bOk ) + { + SwStringInputDlg aDlg(m_xDialog.get(), m_aStrTitle, m_aStrLabel, OUString()); + if (RET_OK == aDlg.run()) + { + const OUString aFormatName(aDlg.GetInputString()); + + if ( !aFormatName.isEmpty() ) + { + size_t n; + for( n = 0; n < m_xTableTable->size(); ++n ) + if( (*m_xTableTable)[n].GetName() == aFormatName ) + break; + + if( n >= m_xTableTable->size() ) + { + // Format with the name does not already exist, so take up. + std::unique_ptr<SwTableAutoFormat> pNewData( + new SwTableAutoFormat(aFormatName)); + bool bGetOk = m_pShell->GetTableAutoFormat( *pNewData ); + SAL_WARN_IF(!bGetOk, "sw.ui", "GetTableAutoFormat failed for: " << aFormatName); + + // Insert sorted!! + for( n = 1; n < m_xTableTable->size(); ++n ) + if( (*m_xTableTable)[ n ].GetName() > aFormatName ) + break; + + m_xTableTable->InsertAutoFormat(n, std::move(pNewData)); + m_xLbFormat->insert_text(m_nDfltStylePos + n, aFormatName); + m_xLbFormat->select(m_nDfltStylePos + n); + bFormatInserted = true; + m_xBtnAdd->set_sensitive(false); + if ( !m_bCoreDataChanged ) + { + m_xBtnCancel->set_label(m_aStrClose); + m_bCoreDataChanged = true; + } + + SelFormatHdl(*m_xLbFormat); + bOk = true; + } + } + + if( !bFormatInserted ) + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Error, VclButtonsType::OkCancel, m_aStrInvalidFormat)); + bOk = RET_CANCEL == xBox->run(); + } + } + else + bOk = true; + } +} + +IMPL_LINK_NOARG(SwAutoFormatDlg, RemoveHdl, weld::Button&, void) +{ + OUString aMessage = m_aStrDelMsg + "\n\n" + + m_xLbFormat->get_selected_text() + "\n"; + + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Question, + VclButtonsType::OkCancel, m_aStrDelTitle)); + xBox->set_secondary_text(aMessage); + + if (xBox->run() == RET_OK) + { + sal_uInt8 nIndex = m_nIndex; + + m_xLbFormat->remove(m_nDfltStylePos + nIndex); + m_xLbFormat->select(m_nDfltStylePos + nIndex - 1); + + m_xTableTable->EraseAutoFormat(nIndex); + m_nIndex = nIndex - 1; + + if( !m_nIndex ) + { + m_xBtnRemove->set_sensitive(false); + m_xBtnRename->set_sensitive(false); + } + + if( !m_bCoreDataChanged ) + { + m_xBtnCancel->set_label(m_aStrClose); + m_bCoreDataChanged = true; + } + } + + SelFormatHdl(*m_xLbFormat); +} + +IMPL_LINK_NOARG(SwAutoFormatDlg, RenameHdl, weld::Button&, void) +{ + bool bOk = false; + while( !bOk ) + { + SwStringInputDlg aDlg(m_xDialog.get(), m_aStrRenameTitle, m_aStrLabel, m_xLbFormat->get_selected_text()); + if (aDlg.run() == RET_OK) + { + bool bFormatRenamed = false; + const OUString aFormatName(aDlg.GetInputString()); + + if ( !aFormatName.isEmpty() ) + { + size_t n; + for( n = 0; n < m_xTableTable->size(); ++n ) + if ((*m_xTableTable)[n].GetName() == aFormatName) + break; + + if( n >= m_xTableTable->size() ) + { + sal_uInt8 nIndex = m_nIndex; + + // no format with this name exists, so rename it + m_xLbFormat->remove(m_nDfltStylePos + nIndex); + std::unique_ptr<SwTableAutoFormat> p( + m_xTableTable->ReleaseAutoFormat(nIndex)); + + p->SetName( aFormatName ); + + // keep all arrays sorted! + for( n = 1; n < m_xTableTable->size(); ++n ) + if ((*m_xTableTable)[n].GetName() > aFormatName) + { + break; + } + + m_xTableTable->InsertAutoFormat( n, std::move(p) ); + m_xLbFormat->insert_text(m_nDfltStylePos + n, aFormatName); + m_xLbFormat->select(m_nDfltStylePos + n); + + if ( !m_bCoreDataChanged ) + { + m_xBtnCancel->set_label(m_aStrClose); + m_bCoreDataChanged = true; + } + + SelFormatHdl(*m_xLbFormat); + bOk = true; + bFormatRenamed = true; + } + } + + if( !bFormatRenamed ) + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Error, VclButtonsType::OkCancel, m_aStrInvalidFormat)); + bOk = RET_CANCEL == xBox->run(); + } + } + else + bOk = true; + } +} + +IMPL_LINK_NOARG(SwAutoFormatDlg, SelFormatHdl, weld::TreeView&, void) +{ + bool bBtnEnable = false; + sal_uInt8 nOldIdx = m_nIndex; + int nSelPos = m_xLbFormat->get_selected_index(); + if (nSelPos >= m_nDfltStylePos) + { + m_nIndex = nSelPos - m_nDfltStylePos; + m_aWndPreview.NotifyChange((*m_xTableTable)[m_nIndex]); + bBtnEnable = 0 != m_nIndex; + UpdateChecks( (*m_xTableTable)[m_nIndex], true ); + } + else + { + m_nIndex = 255; + + SwTableAutoFormat aTmp( SwViewShell::GetShellRes()->aStrNone ); + aTmp.SetFont( false ); + aTmp.SetJustify( false ); + aTmp.SetFrame( false ); + aTmp.SetBackground( false ); + aTmp.SetValueFormat( false ); + aTmp.SetWidthHeight( false ); + + if (nOldIdx != m_nIndex) + m_aWndPreview.NotifyChange(aTmp); + UpdateChecks( aTmp, false ); + } + + m_xBtnRemove->set_sensitive(bBtnEnable); + m_xBtnRename->set_sensitive(bBtnEnable); +} + +short SwAutoFormatDlg::run() +{ + short nRet = SfxDialogController::run(); + if (nRet == RET_OK && m_bSetAutoFormat) + m_pShell->SetTableStyle((*m_xTableTable)[m_nIndex]); + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |