Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/cui/source/tabpages/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 66 kB image not shown  

Quelle  border.cxx   Sprache: C

 
/* -*- 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 <sal/config.h>

#include <sfx2/objsh.hxx>
#include <svx/strings.hrc>
#include <svx/svxids.hrc>

#include <strings.hrc>
#include <bitmaps.hlst>

#include <editeng/boxitem.hxx>
#include <editeng/lineitem.hxx>
#include <border.hxx>
#include <svx/dlgutil.hxx>
#include <dialmgr.hxx>
#include <sfx2/htmlmode.hxx>
#include <vcl/fieldvalues.hxx>
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <svx/dialmgr.hxx>
#include <svx/flagsdef.hxx>
#include <svl/grabbagitem.hxx>
#include <svl/intitem.hxx>
#include <svl/ilstitem.hxx>
#include <svl/int64item.hxx>
#include <sal/macros.h>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <comphelper/lok.hxx>
#include <svtools/unitconv.hxx>

using namespace ::editeng;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::lang::XServiceInfo;
using ::com::sun::star::uno::UNO_QUERY;


/*
 * [Description:]
 * TabPage for setting the border attributes.
 * Needs
 *      a SvxShadowItem: shadow
 *      a SvxBoxItem:    lines left, right, top, bottom,
 *      a SvxBoxInfo:    lines vertical, horizontal, distance, flags
 *
 * Lines can have three conditions:
 *      1. Show     ( -> valid values )
 *      2. Hide     ( -> NULL-Pointer )
 *      3. DontCare ( -> special Valid-Flags in the InfoItem )
 */


// static ----------------------------------------------------------------

const WhichRangesContainer SvxBorderTabPage::pRanges(
    svl::Items<
        SID_ATTR_BORDER_INNER,      SID_ATTR_BORDER_SHADOW,
        SID_ATTR_ALIGN_MARGIN,      SID_ATTR_ALIGN_MARGIN,
        SID_ATTR_BORDER_CONNECT,    SID_ATTR_BORDER_CONNECT,
        SID_SW_COLLAPSING_BORDERS,  SID_SW_COLLAPSING_BORDERS,
        SID_ATTR_BORDER_DIAG_TLBR,  SID_ATTR_BORDER_DIAG_BLTR>);

namespace
{
constexpr int twipsToPt100(sal_Int64 nTwips)
{
    return o3tl::convert(nTwips * 100, o3tl::Length::twip, o3tl::Length::pt);
}
constexpr int s_LineWidths[] = { twipsToPt100(SvxBorderLineWidth::Hairline),
                                 twipsToPt100(SvxBorderLineWidth::VeryThin),
                                 twipsToPt100(SvxBorderLineWidth::Thin),
                                 twipsToPt100(SvxBorderLineWidth::Medium),
                                 twipsToPt100(SvxBorderLineWidth::Thick),
                                 twipsToPt100(SvxBorderLineWidth::ExtraThick),
                                 -1 };
}

static void lcl_SetDecimalDigitsTo1(weld::MetricSpinButton& rField)
{
    auto nMin = rField.denormalize(rField.get_min(FieldUnit::TWIP));
    rField.set_digits(1);
    rField.set_min(rField.normalize(nMin), FieldUnit::TWIP);
}

// returns in pt
static sal_Int64 lcl_GetMinLineWidth(SvxBorderLineStyle aStyle)
{
    switch (aStyle)
    {
    case SvxBorderLineStyle::NONE:
        return 0;

    case SvxBorderLineStyle::SOLID:
    case SvxBorderLineStyle::DOTTED:
    case SvxBorderLineStyle::DASHED:
    case SvxBorderLineStyle::FINE_DASHED:
    case SvxBorderLineStyle::DASH_DOT:
    case SvxBorderLineStyle::DASH_DOT_DOT:
        return 15;

        // Double lines
    case SvxBorderLineStyle::DOUBLEreturn 15;
    case SvxBorderLineStyle::DOUBLE_THIN: return 15;
    case SvxBorderLineStyle::THINTHICK_SMALLGAP: return 20;
    case SvxBorderLineStyle::THINTHICK_MEDIUMGAP: return 15;
    case SvxBorderLineStyle::THINTHICK_LARGEGAP: return 15;
    case SvxBorderLineStyle::THICKTHIN_SMALLGAP: return 20;
    case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP: return 15;
    case SvxBorderLineStyle::THICKTHIN_LARGEGAP: return 15;

    case SvxBorderLineStyle::EMBOSSED: return 15;
    case SvxBorderLineStyle::ENGRAVED: return 15;

    case SvxBorderLineStyle::OUTSET: return 10;
    case SvxBorderLineStyle::INSET: return 10;

    default:
        return 15;
    }
}

// number of preset images to show
const sal_uInt16 BORDER_PRESET_COUNT = 5;

// number of shadow images to show
const sal_uInt16 BORDER_SHADOW_COUNT = 5;

ShadowControlsWrapper::ShadowControlsWrapper(ValueSet& rVsPos, weld::MetricSpinButton& rMfSize, ColorListBox& rLbColor)
    : mrVsPos(rVsPos)
    , mrMfSize(rMfSize)
    , mrLbColor(rLbColor)
{
}

SvxShadowItem ShadowControlsWrapper::GetControlValue(const SvxShadowItem& rItemconst
{
    SvxShadowItem aItem(rItem);
    if (!mrVsPos.IsNoSelection())
    {
        switch (mrVsPos.GetSelectedItemId())
        {
            case 1:
                aItem.SetLocation(SvxShadowLocation::NONE);
                break;
            case 2:
                aItem.SetLocation(SvxShadowLocation::BottomRight);
                break;
            case 3:
                aItem.SetLocation(SvxShadowLocation::TopRight);
                break;
            case 4:
                aItem.SetLocation(SvxShadowLocation::BottomLeft);
                break;
            case 5:
                aItem.SetLocation(SvxShadowLocation::TopLeft);
                break;
            default:
                aItem.SetLocation(SvxShadowLocation::NONE);
                break;
        }
    }
    // Default value was saved; so don't change the aItem's width if the control
    // has not changed its value, to avoid round-trip errors (like twip->cm->twip)
    // E.g., initial 100 twip will become 0.18 cm, which will return as 102 twip
    if (mrMfSize.get_value_changed_from_saved())
        aItem.SetWidth(mrMfSize.denormalize(mrMfSize.get_value(FieldUnit::TWIP)));
    if (!mrLbColor.IsNoSelection())
        aItem.SetColor(mrLbColor.GetSelectEntryColor());
    return aItem;
}

void ShadowControlsWrapper::SetControlValue(const SvxShadowItem& rItem)
{
    switch (rItem.GetLocation())
    {
        case SvxShadowLocation::NONE:
            mrVsPos.SelectItem(1);
            break;
        case SvxShadowLocation::BottomRight:
            mrVsPos.SelectItem(2);
            break;
        case SvxShadowLocation::TopRight:
            mrVsPos.SelectItem(3);
            break;
        case SvxShadowLocation::BottomLeft:
            mrVsPos.SelectItem(4);
            break;
        case SvxShadowLocation::TopLeft:
            mrVsPos.SelectItem(5);
            break;
        default:
            mrVsPos.SetNoSelection();
            break;
    }
    mrVsPos.SaveValue();
    mrMfSize.set_value(mrMfSize.normalize(rItem.GetWidth()), FieldUnit::TWIP);
    mrMfSize.save_value();
    mrLbColor.SelectEntry(rItem.GetColor());
    mrLbColor.SaveValue();
}

bool ShadowControlsWrapper::get_value_changed_from_saved() const
{
    return mrVsPos.IsValueChangedFromSaved() ||
           mrMfSize.get_value_changed_from_saved() ||
           mrLbColor.IsValueChangedFromSaved();
}

void ShadowControlsWrapper::SetControlDontKnow()
{
    mrVsPos.SetNoSelection();
    mrMfSize.set_text(u""_ustr);
    mrLbColor.SetNoSelection();
}

MarginControlsWrapper::MarginControlsWrapper(weld::MetricSpinButton& rMfLeft, weld::MetricSpinButton& rMfRight,
                                             weld::MetricSpinButton& rMfTop, weld::MetricSpinButton& rMfBottom)
    : mrLeftWrp(rMfLeft)
    , mrRightWrp(rMfRight)
    , mrTopWrp(rMfTop)
    , mrBottomWrp(rMfBottom)
{
}

SvxMarginItem MarginControlsWrapper::GetControlValue(const SvxMarginItem &rItem) const
{
    SvxMarginItem aItem(rItem);
    if (mrLeftWrp.get_sensitive())
        aItem.SetLeftMargin(mrLeftWrp.denormalize(mrLeftWrp.get_value(FieldUnit::TWIP)));
    if (mrRightWrp.get_sensitive())
        aItem.SetRightMargin(mrRightWrp.denormalize(mrRightWrp.get_value(FieldUnit::TWIP)));
    if (mrTopWrp.get_sensitive())
        aItem.SetTopMargin(mrTopWrp.denormalize(mrTopWrp.get_value(FieldUnit::TWIP)));
    if (mrBottomWrp.get_sensitive())
        aItem.SetBottomMargin(mrBottomWrp.denormalize(mrBottomWrp.get_value(FieldUnit::TWIP)));
    return aItem;
}

bool MarginControlsWrapper::get_value_changed_from_saved() const
{
    return mrLeftWrp.get_value_changed_from_saved() ||
           mrRightWrp.get_value_changed_from_saved() ||
           mrTopWrp.get_value_changed_from_saved() ||
           mrBottomWrp.get_value_changed_from_saved();
}

void MarginControlsWrapper::SetControlValue(const SvxMarginItem& rItem)
{
    mrLeftWrp.set_value(mrLeftWrp.normalize(rItem.GetLeftMargin()), FieldUnit::TWIP);
    mrRightWrp.set_value(mrRightWrp.normalize(rItem.GetRightMargin()), FieldUnit::TWIP);
    mrTopWrp.set_value(mrTopWrp.normalize(rItem.GetTopMargin()), FieldUnit::TWIP);
    mrBottomWrp.set_value(mrBottomWrp.normalize(rItem.GetBottomMargin()), FieldUnit::TWIP);
    mrLeftWrp.save_value();
    mrRightWrp.save_value();
    mrTopWrp.save_value();
    mrBottomWrp.save_value();
}

void MarginControlsWrapper::SetControlDontKnow()
{
    const OUString sEmpty;
    mrLeftWrp.set_text(sEmpty);
    mrRightWrp.set_text(sEmpty);
    mrTopWrp.set_text(sEmpty);
    mrBottomWrp.set_text(sEmpty);
}

SvxBorderTabPage::SvxBorderTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
    : SfxTabPage(pPage, pController, u"cui/ui/borderpage.ui"_ustr, u"BorderPage"_ustr, &rCoreAttrs)
    , nMinValue(0)
    , nSWMode(SwBorderModes::NONE)
    , mnBoxSlot(SID_ATTR_BORDER_OUTER)
    , mnShadowSlot(SID_ATTR_BORDER_SHADOW)
    , mbHorEnabled(false)
    , mbVerEnabled(false)
    , mbTLBREnabled(false)
    , mbBLTREnabled(false)
    , mbUseMarginItem(false)
    , mbLeftModified(false)
    , mbRightModified(false)
    , mbTopModified(false)
    , mbBottomModified(false)
    , mbSync(true)
    , mbRemoveAdjacentCellBorders(false)
    , bIsCalcDoc(false)
    , m_xWndPresets(new ValueSet(nullptr))
    , m_xWndPresetsWin(new weld::CustomWeld(*m_xBuilder, u"presets"_ustr, *m_xWndPresets))
    , m_xUserDefFT(m_xBuilder->weld_label(u"userdefft"_ustr))
    , m_xFrameSelWin(new weld::CustomWeld(*m_xBuilder, u"framesel"_ustr, m_aFrameSel))
    , m_xLbLineStyle(new SvtLineListBox(m_xBuilder->weld_menu_button(u"linestylelb"_ustr)))
    , m_xLbLineColor(new ColorListBox(m_xBuilder->weld_menu_button(u"linecolorlb"_ustr),
                [this]{ return GetDialogController()->getDialog(); }))
    , m_xLineWidthLB(m_xBuilder->weld_combo_box(u"linewidthlb"_ustr))
    , m_xLineWidthMF(m_xBuilder->weld_metric_spin_button(u"linewidthmf"_ustr, FieldUnit::POINT))
    , m_xSpacingFrame(m_xBuilder->weld_container(u"spacing"_ustr))
    , m_xLeftFT(m_xBuilder->weld_label(u"leftft"_ustr))
    , m_xLeftMF(m_xBuilder->weld_metric_spin_button(u"leftmf"_ustr, FieldUnit::MM))
    , m_xRightFT(m_xBuilder->weld_label(u"rightft"_ustr))
    , m_xRightMF(m_xBuilder->weld_metric_spin_button(u"rightmf"_ustr, FieldUnit::MM))
    , m_xTopFT(m_xBuilder->weld_label(u"topft"_ustr))
    , m_xTopMF(m_xBuilder->weld_metric_spin_button(u"topmf"_ustr, FieldUnit::MM))
    , m_xBottomFT(m_xBuilder->weld_label(u"bottomft"_ustr))
    , m_xBottomMF(m_xBuilder->weld_metric_spin_button(u"bottommf"_ustr, FieldUnit::MM))
    , m_xSynchronizeCB(m_xBuilder->weld_check_button(u"sync"_ustr))
    , m_xShadowFrame(m_xBuilder->weld_container(u"shadow"_ustr))
    , m_xWndShadows(new ValueSet(nullptr))
    , m_xWndShadowsWin(new weld::CustomWeld(*m_xBuilder, u"shadows"_ustr, *m_xWndShadows))
    , m_xFtShadowSize(m_xBuilder->weld_label(u"distanceft"_ustr))
    , m_xEdShadowSize(m_xBuilder->weld_metric_spin_button(u"distancemf"_ustr, FieldUnit::MM))
    , m_xFtShadowColor(m_xBuilder->weld_label(u"shadowcolorft"_ustr))
    , m_xLbShadowColor(new ColorListBox(m_xBuilder->weld_menu_button(u"shadowcolorlb"_ustr),
                [this]{ return GetDialogController()->getDialog(); }))
    , m_xPropertiesFrame(m_xBuilder->weld_container(u"properties"_ustr))
    , m_xMergeWithNextCB(m_xBuilder->weld_check_button(u"mergewithnext"_ustr))
    , m_xMergeAdjacentBordersCB(m_xBuilder->weld_check_button(u"mergeadjacent"_ustr))
    , m_xRemoveAdjacentCellBordersCB(m_xBuilder->weld_check_button(u"rmadjcellborders"_ustr))
    , m_xRemoveAdjacentCellBordersFT(m_xBuilder->weld_label(u"rmadjcellbordersft"_ustr))
{
    static std::vector<OUString> aBorderImageIds;

    if (aBorderImageIds.empty())
    {
        if (comphelper::LibreOfficeKit::isActive())
        {
            aBorderImageIds.insert(aBorderImageIds.end(), {
                RID_SVXBMP_CELL_NONE_32,
                RID_SVXBMP_CELL_ALL_32,
                RID_SVXBMP_CELL_LR_32,
                RID_SVXBMP_CELL_TB_32,
                RID_SVXBMP_CELL_L_32,
                RID_SVXBMP_CELL_DIAG_32
            });
        }
        else
        {
            aBorderImageIds.insert(aBorderImageIds.end(), {
                RID_SVXBMP_CELL_NONE,
                RID_SVXBMP_CELL_ALL,
                RID_SVXBMP_CELL_LR,
                RID_SVXBMP_CELL_TB,
                RID_SVXBMP_CELL_L,
                RID_SVXBMP_CELL_DIAG
            });
        }
        aBorderImageIds.insert(aBorderImageIds.end(), {
            RID_SVXBMP_HOR_NONE,
            RID_SVXBMP_HOR_OUTER,
            RID_SVXBMP_HOR_HOR,
            RID_SVXBMP_HOR_ALL,
            RID_SVXBMP_HOR_OUTER2,
            RID_SVXBMP_VER_NONE,
            RID_SVXBMP_VER_OUTER,
            RID_SVXBMP_VER_VER,
            RID_SVXBMP_VER_ALL,
            RID_SVXBMP_VER_OUTER2,
            RID_SVXBMP_TABLE_NONE,
            RID_SVXBMP_TABLE_OUTER,
            RID_SVXBMP_TABLE_OUTERH,
            RID_SVXBMP_TABLE_ALL,
            RID_SVXBMP_TABLE_OUTER2
        });
    }

    for (auto const & rImageId : aBorderImageIds)
        m_aBorderImgVec.emplace_back(StockImage::Yes, rImageId);

    static std::vector<OUString> aShadowImageIds;
    if (aShadowImageIds.empty())
    {
        if (comphelper::LibreOfficeKit::isActive())
        {
            aShadowImageIds.insert(aShadowImageIds.end(), {
                RID_SVXBMP_SHADOWNONE_32,
                RID_SVXBMP_SHADOW_BOT_RIGHT_32,
                RID_SVXBMP_SHADOW_TOP_RIGHT_32,
                RID_SVXBMP_SHADOW_BOT_LEFT_32,
                RID_SVXBMP_SHADOW_TOP_LEFT_32
            });
        }
        else
        {
            aShadowImageIds.insert(aShadowImageIds.end(), {
                RID_SVXBMP_SHADOWNONE,
                RID_SVXBMP_SHADOW_BOT_RIGHT,
                RID_SVXBMP_SHADOW_TOP_RIGHT,
                RID_SVXBMP_SHADOW_BOT_LEFT,
                RID_SVXBMP_SHADOW_TOP_LEFT
            });
        }
    }

    for (auto const & rImageId : aShadowImageIds)
        m_aShadowImgVec.emplace_back(StockImage::Yes, rImageId);

    assert(m_aShadowImgVec.size() == BORDER_SHADOW_COUNT);

    // this page needs ExchangeSupport
    SetExchangeSupport();

    /*  Use SvxMarginItem instead of margins from SvxBoxItem, if present.
        ->  Remember this state in mbUseMarginItem, because other special handling
            is needed across various functions... */

    mbUseMarginItem = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_ALIGN_MARGIN)) != SfxItemState::UNKNOWN;

    if (const SfxIntegerListItem* p = rCoreAttrs.GetItemIfSet(SID_ATTR_BORDER_STYLES))
    {
        std::vector<sal_Int32> aUsedStyles = p->GetList();
        for (int aUsedStyle : aUsedStyles)
            maUsedBorderStyles.insert(static_cast<SvxBorderLineStyle>(aUsedStyle));
    }

    if (const SfxInt64Item* p = rCoreAttrs.GetItemIfSet(SID_ATTR_BORDER_DEFAULT_WIDTH))
    {
        // The caller specifies default line width.  Honor it.
        SetLineWidth(p->GetValue());
    }

    // set metric
    FieldUnit eFUnit = GetModuleFieldUnit( rCoreAttrs );

    if( mbUseMarginItem )
    {
        // copied from SvxAlignmentTabPage
        switch ( eFUnit )
        {
            //  #103396# the default value (1pt) can't be accurately represented in
            //  inches or pica with two decimals, so point is used instead.
            case FieldUnit::PICA:
            case FieldUnit::INCH:
            case FieldUnit::FOOT:
            case FieldUnit::MILE:
                eFUnit = FieldUnit::POINT;
                break;

            case FieldUnit::CM:
            case FieldUnit::M:
            case FieldUnit::KM:
                eFUnit = FieldUnit::MM;
                break;
            default: ;//prevent warning
        }
    }
    else
    {
        switch ( eFUnit )
        {
            case FieldUnit::M:
            case FieldUnit::KM:
                eFUnit = FieldUnit::MM;
                break;
            default: ; //prevent warning
        }
    }

    SetFieldUnit(*m_xEdShadowSize, eFUnit);

    sal_uInt16 nWhich = GetWhich( SID_ATTR_BORDER_INNER, false );
    bool bIsDontCare = true;

    if ( rCoreAttrs.GetItemState( nWhich ) >= SfxItemState::DEFAULT )
    {
        // paragraph or table
        const SvxBoxInfoItem* pBoxInfo =
            static_cast<const SvxBoxInfoItem*>(&( rCoreAttrs.Get( nWhich ) ));

        mbHorEnabled = pBoxInfo->IsHorEnabled();
        mbVerEnabled = pBoxInfo->IsVerEnabled();
        mbTLBREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_TLBR)) != SfxItemState::UNKNOWN;
        mbBLTREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_BLTR)) != SfxItemState::UNKNOWN;

        if(pBoxInfo->IsDist())
        {
            SetFieldUnit(*m_xLeftMF, eFUnit);
            SetFieldUnit(*m_xRightMF, eFUnit);
            SetFieldUnit(*m_xTopMF, eFUnit);
            SetFieldUnit(*m_xBottomMF, eFUnit);
            m_xSynchronizeCB->connect_toggled(LINK(this, SvxBorderTabPage, SyncHdl_Impl));
            m_xLeftMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
            m_xRightMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
            m_xTopMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
            m_xBottomMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
        }
        else
        {
            m_xSpacingFrame->hide();
        }
        bIsDontCare = !pBoxInfo->IsValid( SvxBoxInfoItemValidFlags::DISABLE );
    }
    if(!mbUseMarginItem && eFUnit == FieldUnit::MM && MapUnit::MapTwip == rCoreAttrs.GetPool()->GetMetric( GetWhich( SID_ATTR_BORDER_INNER ) ))
    {
        //#i91548# changing the number of decimal digits changes the minimum values, too
        lcl_SetDecimalDigitsTo1(*m_xLeftMF);
        lcl_SetDecimalDigitsTo1(*m_xRightMF);
        lcl_SetDecimalDigitsTo1(*m_xTopMF);
        lcl_SetDecimalDigitsTo1(*m_xBottomMF);
        lcl_SetDecimalDigitsTo1(*m_xEdShadowSize);
    }

    FrameSelFlags nFlags = FrameSelFlags::Outer;
    if( mbHorEnabled )
        nFlags |= FrameSelFlags::InnerHorizontal;
    if( mbVerEnabled )
        nFlags |= FrameSelFlags::InnerVertical;
    if( mbTLBREnabled )
        nFlags |= FrameSelFlags::DiagonalTLBR;
    if( mbBLTREnabled )
        nFlags |= FrameSelFlags::DiagonalBLTR;
    if( bIsDontCare )
        nFlags |= FrameSelFlags::DontCare;
    m_aFrameSel.Initialize( nFlags );

    m_aFrameSel.SetSelectHdl(LINK(this, SvxBorderTabPage, LinesChanged_Impl));
    m_xLbLineStyle->SetSelectHdl( LINK( this, SvxBorderTabPage, SelStyleHdl_Impl ) );
    m_xLbLineColor->SetSelectHdl( LINK( this, SvxBorderTabPage, SelColHdl_Impl ) );
    m_xLineWidthLB->connect_changed(LINK(this, SvxBorderTabPage, ModifyWidthLBHdl_Impl));
    m_xLineWidthMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyWidthMFHdl_Impl));
    m_xWndPresets->SetSelectHdl( LINK( this, SvxBorderTabPage, SelPreHdl_Impl ) );
    m_xWndShadows->SetSelectHdl( LINK( this, SvxBorderTabPage, SelSdwHdl_Impl ) );

    FillValueSets();
    FillLineListBox_Impl();

    // Reapply line width: probably one of predefined values should be selected
    SetLineWidth(m_xLineWidthMF->get_value(FieldUnit::NONE));

    // connections
    const SfxPoolItem* pItem = nullptr;
    if (rCoreAttrs.HasItem(GetWhich(SID_ATTR_PARA_GRABBAG), &pItem))
    {
        const SfxGrabBagItem* pGrabBag = static_cast<const SfxGrabBagItem*>(pItem);
        auto it = pGrabBag->GetGrabBag().find(u"DialogUseCharAttr"_ustr);
        if (it != pGrabBag->GetGrabBag().end())
        {
            bool bDialogUseCharAttr = false;
            it->second >>= bDialogUseCharAttr;
            if (bDialogUseCharAttr)
            {
                mnShadowSlot = SID_ATTR_CHAR_SHADOW;
                mnBoxSlot = SID_ATTR_CHAR_BOX;
            }
        }
    }

    bool bSupportsShadow = !SfxItemPool::IsSlot(GetWhich(mnShadowSlot));
    if( bSupportsShadow )
        m_xShadowControls.reset(new ShadowControlsWrapper(*m_xWndShadows, *m_xEdShadowSize, *m_xLbShadowColor));
    else
        HideShadowControls();

    if (mbUseMarginItem)
        m_xMarginControls.reset(new MarginControlsWrapper(*m_xLeftMF, *m_xRightMF, *m_xTopMF, *m_xBottomMF));

    // checkbox "Merge with next paragraph" only visible for Writer dialog format.paragraph
    m_xMergeWithNextCB->hide();
    // checkbox "Merge adjacent line styles" only visible for Writer dialog format.table
    m_xMergeAdjacentBordersCB->hide();

    if (SfxObjectShell* pDocSh = SfxObjectShell::Current())
    {
        Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY );
        if ( xSI.is() )
            bIsCalcDoc = xSI->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr);
    }
    if( bIsCalcDoc )
    {
        m_xRemoveAdjacentCellBordersCB->connect_toggled(LINK(this, SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl));
        m_xRemoveAdjacentCellBordersCB->show();
        m_xRemoveAdjacentCellBordersCB->set_sensitive(false);
    }
    else
    {
        m_xRemoveAdjacentCellBordersCB->hide();
        m_xRemoveAdjacentCellBordersFT->hide();
    }
}

SvxBorderTabPage::~SvxBorderTabPage()
{
    m_xLbShadowColor.reset();
    m_xWndShadowsWin.reset();
    m_xWndShadows.reset();
    m_xLbLineColor.reset();
    m_xLbLineStyle.reset();
    m_xFrameSelWin.reset();
    m_xWndPresetsWin.reset();
    m_xWndPresets.reset();
}

std::unique_ptr<SfxTabPage> SvxBorderTabPage::Create( weld::Container* pPage, weld::DialogController* pController,
                                             const SfxItemSet* rAttrSet )
{
    return std::make_unique<SvxBorderTabPage>(pPage, pController, *rAttrSet);
}

void SvxBorderTabPage::ResetFrameLine_Impl( svx::FrameBorderType eBorder, const SvxBorderLine* pCoreLine, bool bValid )
{
    if( m_aFrameSel.IsBorderEnabled( eBorder ) )
    {
        if( bValid )
            m_aFrameSel.ShowBorder( eBorder, pCoreLine );
        else
            m_aFrameSel.SetBorderDontCare( eBorder );
    }
}

bool SvxBorderTabPage::IsBorderLineStyleAllowed( SvxBorderLineStyle nStyle ) const
{
    if (maUsedBorderStyles.empty())
        // All border styles are allowed.
        return true;

    return maUsedBorderStyles.count(nStyle) > 0;
}

void SvxBorderTabPage::Reset( const SfxItemSet* rSet )
{
    SfxItemPool* pPool = rSet->GetPool();

    if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR))
    {
        sal_uInt16 nBorderDiagId = pPool->GetWhichIDFromSlotID(SID_ATTR_BORDER_DIAG_TLBR);
        if (const SvxLineItem* pLineItem = static_cast<const SvxLineItem*>(rSet->GetItem(nBorderDiagId)))
            m_aFrameSel.ShowBorder(svx::FrameBorderType::TLBR, pLineItem->GetLine());
        else
            m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::TLBR);
    }

    if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR))
    {
        sal_uInt16 nBorderDiagId = pPool->GetWhichIDFromSlotID(SID_ATTR_BORDER_DIAG_BLTR);
        if (const SvxLineItem* pLineItem = static_cast<const SvxLineItem*>(rSet->GetItem(nBorderDiagId)))
            m_aFrameSel.ShowBorder(svx::FrameBorderType::BLTR, pLineItem->GetLine());
        else
            m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::BLTR);
    }

    if (m_xShadowControls)
    {
        sal_uInt16 nShadowId = pPool->GetWhichIDFromSlotID(mnShadowSlot);
        const SfxPoolItem* pItem = rSet->GetItem(nShadowId);
        if (pItem)
            m_xShadowControls->SetControlValue(*static_cast<const SvxShadowItem*>(pItem));
        else
            m_xShadowControls->SetControlDontKnow();
    }

    if (m_xMarginControls)
    {
        sal_uInt16 nAlignMarginId = pPool->GetWhichIDFromSlotID(SID_ATTR_ALIGN_MARGIN);
        const SfxPoolItem* pItem = rSet->GetItem(nAlignMarginId);
        if (pItem)
            m_xMarginControls->SetControlValue(*static_cast<const SvxMarginItem*>(pItem));
        else
            m_xMarginControls->SetControlDontKnow();
    }

    sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhichIDFromSlotID(SID_SW_COLLAPSING_BORDERS);
    const SfxBoolItem *pMergeAdjacentBorders = static_cast<const SfxBoolItem*>(rSet->GetItem(nMergeAdjacentBordersId));
    if (!pMergeAdjacentBorders)
        m_xMergeAdjacentBordersCB->set_state(TRISTATE_INDET);
    else
        m_xMergeAdjacentBordersCB->set_active(pMergeAdjacentBorders->GetValue());
    m_xMergeAdjacentBordersCB->save_state();

    sal_uInt16 nMergeWithNextId = pPool->GetWhichIDFromSlotID(SID_ATTR_BORDER_CONNECT);
    const SfxBoolItem *pMergeWithNext = static_cast<const SfxBoolItem*>(rSet->GetItem(nMergeWithNextId));
    if (!pMergeWithNext)
        m_xMergeWithNextCB->set_state(TRISTATE_INDET);
    else
        m_xMergeWithNextCB->set_active(pMergeWithNext->GetValue());
    m_xMergeWithNextCB->save_state();

    const SvxBoxItem*       pBoxItem;
    const SvxBoxInfoItem*   pBoxInfoItem;
    sal_uInt16              nWhichBox       = GetWhich(mnBoxSlot);
    MapUnit                 eCoreUnit;

    pBoxItem  = static_cast<const SvxBoxItem*>(GetItem( *rSet, mnBoxSlot ));

    pBoxInfoItem = GetItem( *rSet, SID_ATTR_BORDER_INNER, false );

    eCoreUnit = pPool->GetMetric( nWhichBox );

    if ( pBoxItem && pBoxInfoItem ) // -> Don't Care
    {
        ResetFrameLine_Impl( svx::FrameBorderType::Left,   pBoxItem->GetLeft(),     pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::LEFT ) );
        ResetFrameLine_Impl( svx::FrameBorderType::Right,  pBoxItem->GetRight(),    pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::RIGHT ) );
        ResetFrameLine_Impl( svx::FrameBorderType::Top,    pBoxItem->GetTop(),      pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::TOP ) );
        ResetFrameLine_Impl( svx::FrameBorderType::Bottom, pBoxItem->GetBottom(),   pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) );
        ResetFrameLine_Impl( svx::FrameBorderType::Vertical,    pBoxInfoItem->GetVert(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::VERT ) );
        ResetFrameLine_Impl( svx::FrameBorderType::Horizontal,    pBoxInfoItem->GetHori(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::HORI ) );


        // distance inside

        if( !mbUseMarginItem )
        {
            if (m_xLeftMF->get_visible())
            {
                SetMetricValue(*m_xLeftMF,    pBoxInfoItem->GetDefDist(), eCoreUnit);
                SetMetricValue(*m_xRightMF,   pBoxInfoItem->GetDefDist(), eCoreUnit);
                SetMetricValue(*m_xTopMF,     pBoxInfoItem->GetDefDist(), eCoreUnit);
                SetMetricValue(*m_xBottomMF,  pBoxInfoItem->GetDefDist(), eCoreUnit);

                nMinValue = m_xLeftMF->get_value(FieldUnit::NONE);

                if ( pBoxInfoItem->IsDist() )
                {
                    if( rSet->GetItemState( nWhichBox ) >= SfxItemState::DEFAULT )
                    {
                        bool bIsAnyBorderVisible = m_aFrameSel.IsAnyBorderVisible();
                        if( !bIsAnyBorderVisible || !pBoxInfoItem->IsMinDist() )
                        {
                            m_xLeftMF->set_min(0, FieldUnit::NONE);
                            m_xRightMF->set_min(0, FieldUnit::NONE);
                            m_xTopMF->set_min(0, FieldUnit::NONE);
                            m_xBottomMF->set_min(0, FieldUnit::NONE);
                        }
                        tools::Long nLeftDist = pBoxItem->GetDistance( SvxBoxItemLine::LEFT);
                        SetMetricValue(*m_xLeftMF, nLeftDist, eCoreUnit);
                        tools::Long nRightDist = pBoxItem->GetDistance( SvxBoxItemLine::RIGHT);
                        SetMetricValue(*m_xRightMF, nRightDist, eCoreUnit);
                        tools::Long nTopDist = pBoxItem->GetDistance( SvxBoxItemLine::TOP);
                        SetMetricValue( *m_xTopMF, nTopDist, eCoreUnit );
                        tools::Long nBottomDist = pBoxItem->GetDistance( SvxBoxItemLine::BOTTOM);
                        SetMetricValue( *m_xBottomMF, nBottomDist, eCoreUnit );

                        // if the distance is set with no active border line
                        // or it is null with an active border line
                        // no automatic changes should be made
                        const tools::Long nDefDist = bIsAnyBorderVisible ? pBoxInfoItem->GetDefDist() : 0;
                        bool bDiffDist = (nDefDist != nLeftDist ||
                                    nDefDist != nRightDist ||
                                    nDefDist != nTopDist   ||
                                    nDefDist != nBottomDist);
                        if ((pBoxItem->GetSmallestDistance() || bIsAnyBorderVisible) && bDiffDist )
                        {
                            mbLeftModified = true;
                            mbRightModified = true;
                            mbTopModified = true;
                            mbBottomModified = true;
                        }
                    }
                    else
                    {
                        // #106224# different margins -> do not fill the edits
                        m_xLeftMF->set_text( OUString() );
                        m_xRightMF->set_text( OUString() );
                        m_xTopMF->set_text( OUString() );
                        m_xBottomMF->set_text( OUString() );
                    }
                }
                m_xLeftMF->save_value();
                m_xRightMF->save_value();
                m_xTopMF->save_value();
                m_xBottomMF->save_value();
            }
        }
    }
    else
    {
        // avoid ResetFrameLine-calls:
        m_aFrameSel.HideAllBorders();
    }

    if( !m_aFrameSel.IsAnyBorderVisible() )
        m_aFrameSel.DeselectAllBorders();

    // depict line (color) in controllers if unambiguous:

    {
        // Do all visible lines show the same line widths?
        tools::Long nWidth;
        SvxBorderLineStyle nStyle;
        bool bWidthEq = m_aFrameSel.GetVisibleWidth( nWidth, nStyle );
        if( bWidthEq )
        {
            // Determine the width first as some styles can be missing depending on it
            sal_Int64 nWidthPt =  static_cast<sal_Int64>(vcl::ConvertDoubleValue(
                        sal_Int64( nWidth ), m_xLineWidthMF->get_digits(),
                        MapUnit::MapTwip, FieldUnit::POINT ));
            SetLineWidth(nWidthPt);
            m_xLbLineStyle->SetWidth(nWidth);

            // then set the style
            m_xLbLineStyle->SelectEntry( nStyle );
        }
        else
            m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID);

        // Do all visible lines show the same line color?
        Color aColor;
        bool bColorEq = m_aFrameSel.GetVisibleColor( aColor );
        if( !bColorEq )
            aColor = COL_BLACK;

        m_xLbLineColor->SelectEntry(aColor);
        auto nTextColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor();
        m_xLbLineStyle->SetColor(nTextColor);

        // Select all visible lines, if they are all equal.
        if( bWidthEq && bColorEq )
            m_aFrameSel.SelectAllVisibleBorders();

        // set the current style and color (caches style in control even if nothing is selected)
        SelStyleHdl_Impl(*m_xLbLineStyle);
        SelColHdl_Impl(*m_xLbLineColor);
    }

    bool bEnable = m_xWndShadows->GetSelectedItemId() > 1 ;
    m_xFtShadowSize->set_sensitive(bEnable);
    m_xEdShadowSize->set_sensitive(bEnable);
    m_xFtShadowColor->set_sensitive(bEnable);
    m_xLbShadowColor->set_sensitive(bEnable);

    m_xWndPresets->SetNoSelection();

    // - no line - should not be selected

    if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE)
    {
        m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID);
        SelStyleHdl_Impl(*m_xLbLineStyle);
    }

    const SfxUInt16Item* pHtmlModeItem = rSet->GetItemIfSet(SID_HTML_MODE, false);
    if(!pHtmlModeItem)
    {
        if (SfxObjectShell* pShell = SfxObjectShell::Current())
            pHtmlModeItem = pShell->GetItem(SID_HTML_MODE);
    }
    if(pHtmlModeItem)
    {
        sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue();
        if(nHtmlMode & HTMLMODE_ON)
        {
            // there are no shadows in Html-mode and only complete borders
            m_xShadowFrame->set_sensitive(false);

            if( !(nSWMode & SwBorderModes::TABLE) )
            {
                m_xUserDefFT->set_sensitive(false);
                m_xFrameSelWin->set_sensitive(false);
                m_xWndPresets->RemoveItem(3);
                m_xWndPresets->RemoveItem(4);
                m_xWndPresets->RemoveItem(5);
            }
        }
    }

    LinesChanged_Impl( nullptr );
    if (m_xLeftMF->get_value(FieldUnit::NONE) == m_xRightMF->get_value(FieldUnit::NONE) &&
        m_xTopMF->get_value(FieldUnit::NONE) == m_xBottomMF->get_value(FieldUnit::NONE) &&
        m_xTopMF->get_value(FieldUnit::NONE) == m_xLeftMF->get_value(FieldUnit::NONE))
    {
        mbSync = true;
    }
    else
        mbSync = false;
    m_xSynchronizeCB->set_active(mbSync);

    mbRemoveAdjacentCellBorders = false;
    m_xRemoveAdjacentCellBordersCB->set_active(false);
    m_xRemoveAdjacentCellBordersCB->set_sensitive(false);
}

void SvxBorderTabPage::ChangesApplied()
{
    m_xLeftMF->save_value();
    m_xRightMF->save_value();
    m_xTopMF->save_value();
    m_xBottomMF->save_value();
    m_xMergeWithNextCB->save_state();
    m_xMergeAdjacentBordersCB->save_state();
}

DeactivateRC SvxBorderTabPage::DeactivatePage( SfxItemSet* _pSet )
{
    if ( _pSet )
        FillItemSet( _pSet );

    return DeactivateRC::LeavePage;
}

bool SvxBorderTabPage::FillItemSet( SfxItemSet* rCoreAttrs )
{
    bool bAttrsChanged = false;

    SfxItemPool* pPool = rCoreAttrs->GetPool();

    if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR) &&
        m_aFrameSel.GetFrameBorderState(svx::FrameBorderType::TLBR) != svx::FrameBorderState::DontCare)
    {
        if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_DIAG_TLBR))
        {
            SvxLineItem aLineItem(*static_cast<const SvxLineItem*>(pOldItem));
            aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::TLBR));
            rCoreAttrs->Put(aLineItem);
            bAttrsChanged = true;
        }
    }

    if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR) &&
        m_aFrameSel.GetFrameBorderState(svx::FrameBorderType::BLTR) != svx::FrameBorderState::DontCare)
    {
        if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_DIAG_BLTR))
        {
            SvxLineItem aLineItem(*static_cast<const SvxLineItem*>(pOldItem));
            aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::BLTR));
            rCoreAttrs->Put(aLineItem);
            bAttrsChanged = true;
        }
    }

    if (m_xShadowControls && m_xShadowControls->get_value_changed_from_saved())
    {
        if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, mnShadowSlot))
        {
            const SvxShadowItem& rOldShadowItem = *static_cast<const SvxShadowItem*>(pOldItem);
            rCoreAttrs->Put(m_xShadowControls->GetControlValue(rOldShadowItem));
            bAttrsChanged = true;
        }
    }

    if (m_xMarginControls && m_xMarginControls->get_value_changed_from_saved())
    {
        if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_ALIGN_MARGIN))
        {
            const SvxMarginItem& rOldMarginItem = *static_cast<const SvxMarginItem*>(pOldItem);
            rCoreAttrs->Put(m_xMarginControls->GetControlValue(rOldMarginItem));
            bAttrsChanged = true;
        }
    }

    if (m_xMergeAdjacentBordersCB->get_state_changed_from_saved())
    {
        auto nState = m_xMergeAdjacentBordersCB->get_state();
        if (nState == TRISTATE_INDET)
        {
            sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhichIDFromSlotID(SID_SW_COLLAPSING_BORDERS);
            rCoreAttrs->ClearItem(nMergeAdjacentBordersId);
        }
        else
        {
            if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_SW_COLLAPSING_BORDERS))
            {
                std::unique_ptr<SfxBoolItem> xNewItem(static_cast<SfxBoolItem*>(pOldItem->Clone()));
                xNewItem->SetValue(static_cast<bool>(nState));
                rCoreAttrs->Put(std::move(xNewItem));
            }
        }
        bAttrsChanged = true;
    }

    if (m_xMergeWithNextCB->get_state_changed_from_saved())
    {
        auto nState = m_xMergeWithNextCB->get_state();
        if (nState == TRISTATE_INDET)
        {
            sal_uInt16 nMergeWithNextId = pPool->GetWhichIDFromSlotID(SID_ATTR_BORDER_CONNECT);
            rCoreAttrs->ClearItem(nMergeWithNextId);
        }
        else
        {
            if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_CONNECT))
            {
                std::unique_ptr<SfxBoolItem> xNewItem(static_cast<SfxBoolItem*>(pOldItem->Clone()));
                xNewItem->SetValue(static_cast<bool>(nState));
                rCoreAttrs->Put(std::move(xNewItem));
            }
        }
        bAttrsChanged = true;
    }

    bool                  bPut          = true;
    sal_uInt16            nBoxWhich     = GetWhich( mnBoxSlot );
    sal_uInt16            nBoxInfoWhich = pPool->GetWhichIDFromSlotID( SID_ATTR_BORDER_INNER, false );
    const SfxItemSet&     rOldSet       = GetItemSet();
    SvxBoxItem            aBoxItem      ( nBoxWhich );
    SvxBoxInfoItem        aBoxInfoItem  ( nBoxInfoWhich );
    const SvxBoxItem*     pOldBoxItem = static_cast<const SvxBoxItem*>(GetOldItem( *rCoreAttrs, mnBoxSlot ));

    MapUnit eCoreUnit = rOldSet.GetPool()->GetMetric( nBoxWhich );


    // outer border:

    std::pair<svx::FrameBorderType,SvxBoxItemLine> eTypes1[] = {
                                { svx::FrameBorderType::Top,SvxBoxItemLine::TOP },
                                { svx::FrameBorderType::Bottom,SvxBoxItemLine::BOTTOM },
                                { svx::FrameBorderType::Left,SvxBoxItemLine::LEFT },
                                { svx::FrameBorderType::Right,SvxBoxItemLine::RIGHT },
                            };

    for (std::pair<svx::FrameBorderType,SvxBoxItemLine> const & i : eTypes1)
        aBoxItem.SetLine( m_aFrameSel.GetFrameBorderStyle( i.first ), i.second );


    aBoxItem.SetRemoveAdjacentCellBorder( mbRemoveAdjacentCellBorders );
    // border hor/ver and TableFlag

    std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> eTypes2[] = {
                                { svx::FrameBorderType::Horizontal,SvxBoxInfoItemLine::HORI },
                                { svx::FrameBorderType::Vertical,SvxBoxInfoItemLine::VERT }
                            };
    for (std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> const & j : eTypes2)
        aBoxInfoItem.SetLine( m_aFrameSel.GetFrameBorderStyle( j.first ), j.second );

    aBoxInfoItem.EnableHor( mbHorEnabled );
    aBoxInfoItem.EnableVer( mbVerEnabled );


    // inner distance

    if (m_xLeftMF->get_visible())
    {
        // #i40405# enable distance controls for next dialog call
        aBoxInfoItem.SetDist( true );

        if( !mbUseMarginItem )
        {
            // #106224# all edits empty: do nothing
            if( !m_xLeftMF->get_text().isEmpty() || !m_xRightMF->get_text().isEmpty() ||
                !m_xTopMF->get_text().isEmpty() || !m_xBottomMF->get_text().isEmpty() )
            {
                const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER );
                if (
                    !pOldBoxItem ||
                    m_xLeftMF->get_value_changed_from_saved() ||
                    m_xRightMF->get_value_changed_from_saved() ||
                    m_xTopMF->get_value_changed_from_saved() ||
                    m_xBottomMF->get_value_changed_from_saved() ||
                    nMinValue == m_xLeftMF->get_value(FieldUnit::NONE) ||
                    nMinValue == m_xRightMF->get_value(FieldUnit::NONE) ||
                    nMinValue == m_xTopMF->get_value(FieldUnit::NONE) ||
                    nMinValue == m_xBottomMF->get_value(FieldUnit::NONE) ||
                    (pOldBoxInfoItem && !pOldBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::DISTANCE))
                   )
                {
                    aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xLeftMF, eCoreUnit )), SvxBoxItemLine::LEFT  );
                    aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xRightMF, eCoreUnit )), SvxBoxItemLine::RIGHT );
                    aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xTopMF, eCoreUnit )), SvxBoxItemLine::TOP   );
                    aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xBottomMF, eCoreUnit )), SvxBoxItemLine::BOTTOM);
                }
                else
                {
                    aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::LEFT ), SvxBoxItemLine::LEFT);
                    aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::RIGHT),  SvxBoxItemLine::RIGHT);
                    aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::TOP  ), SvxBoxItemLine::TOP);
                    aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::BOTTOM), SvxBoxItemLine::BOTTOM);
                }
                aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::DISTANCE );
            }
        }
    }


    // note Don't Care Status in the Info-Item:

    aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::TOP,    m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Top )    != svx::FrameBorderState::DontCare );
    aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Bottom ) != svx::FrameBorderState::DontCare );
    aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::LEFT,   m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Left )   != svx::FrameBorderState::DontCare );
    aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::RIGHT,  m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Right )  != svx::FrameBorderState::DontCare );
    aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::HORI,   m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Horizontal )    != svx::FrameBorderState::DontCare );
    aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::VERT,   m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Vertical )    != svx::FrameBorderState::DontCare );


    // Put or Clear of the border?

    bPut = true;

    if (   SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxWhich,     false ))
    {
        bPut = aBoxItem != static_cast<const SvxBoxItem&>(rOldSet.Get(nBoxWhich));
    }
    if(  SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxInfoWhich, false ) )
    {
        const SvxBoxInfoItem& rOldBoxInfo = static_cast<const SvxBoxInfoItem&>(
                                rOldSet.Get(nBoxInfoWhich));

        aBoxInfoItem.SetMinDist( rOldBoxInfo.IsMinDist() );
        aBoxInfoItem.SetDefDist( rOldBoxInfo.GetDefDist() );
        bPut |= (aBoxInfoItem != rOldBoxInfo );
    }

    if ( bPut )
    {
        if ( !pOldBoxItem || *pOldBoxItem != aBoxItem )
        {
            rCoreAttrs->Put( aBoxItem );
            bAttrsChanged = true;
        }
        const SfxPoolItem* pOld = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER, false );

        if ( !pOld || *static_cast<const SvxBoxInfoItem*>(pOld) != aBoxInfoItem )
        {
            rCoreAttrs->Put( aBoxInfoItem );
            bAttrsChanged = true;
        }
    }
    else
    {
        rCoreAttrs->ClearItem( nBoxWhich );
        rCoreAttrs->ClearItem( nBoxInfoWhich );
    }

    return bAttrsChanged;
}

void SvxBorderTabPage::HideShadowControls()
{
    m_xShadowFrame->hide();
}

#define IID_PRE_CELL_NONE       1
#define IID_PRE_CELL_ALL        2
#define IID_PRE_CELL_LR         3
#define IID_PRE_CELL_TB         4
#define IID_PRE_CELL_L          5
#define IID_PRE_CELL_DIAG       6
#define IID_PRE_HOR_NONE        7
#define IID_PRE_HOR_OUTER       8
#define IID_PRE_HOR_HOR         9
#define IID_PRE_HOR_ALL         10
#define IID_PRE_HOR_OUTER2      11
#define IID_PRE_VER_NONE        12
#define IID_PRE_VER_OUTER       13
#define IID_PRE_VER_VER         14
#define IID_PRE_VER_ALL         15
#define IID_PRE_VER_OUTER2      16
#define IID_PRE_TABLE_NONE      17
#define IID_PRE_TABLE_OUTER     18
#define IID_PRE_TABLE_OUTERH    19
#define IID_PRE_TABLE_ALL       20
#define IID_PRE_TABLE_OUTER2    21

IMPL_LINK_NOARG(SvxBorderTabPage, SelPreHdl_Impl, ValueSet*, void)
{
    const svx::FrameBorderState SHOW = svx::FrameBorderState::Show;
    const svx::FrameBorderState HIDE = svx::FrameBorderState::Hide;
    const svx::FrameBorderState DONT = svx::FrameBorderState::DontCare;

    static const svx::FrameBorderState ppeStates[][ svx::FRAMEBORDERTYPE_COUNT ] =
    {                   /*    Left  Right Top   Bot   Hor   Ver   TLBR  BLTR */
/* ---------------------+--------------------------------------------------- */
/* IID_PRE_CELL_NONE    */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_CELL_ALL     */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_CELL_LR      */  { SHOW, SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_CELL_TB      */  { HIDE, HIDE, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_CELL_L       */  { SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_CELL_DIAG    */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, SHOW, SHOW },
/* IID_PRE_HOR_NONE     */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_HOR_OUTER    */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_HOR_HOR      */  { HIDE, HIDE, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE },
/* IID_PRE_HOR_ALL      */  { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE },
/* IID_PRE_HOR_OUTER2   */  { SHOW, SHOW, SHOW, SHOW, DONT, HIDE, HIDE, HIDE },
/* IID_PRE_VER_NONE     */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_VER_OUTER    */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_VER_VER      */  { SHOW, SHOW, HIDE, HIDE, HIDE, SHOW, HIDE, HIDE },
/* IID_PRE_VER_ALL      */  { SHOW, SHOW, SHOW, SHOW, HIDE, SHOW, HIDE, HIDE },
/* IID_PRE_VER_OUTER2   */  { SHOW, SHOW, SHOW, SHOW, HIDE, DONT, HIDE, HIDE },
/* IID_PRE_TABLE_NONE   */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_TABLE_OUTER  */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
/* IID_PRE_TABLE_OUTERH */  { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE },
/* IID_PRE_TABLE_ALL    */  { SHOW, SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE },
/* IID_PRE_TABLE_OUTER2 */  { SHOW, SHOW, SHOW, SHOW, DONT, DONT, HIDE, HIDE }
    };

    // first hide and deselect all frame borders
    m_aFrameSel.HideAllBorders();
    m_aFrameSel.DeselectAllBorders();

    // Using image ID to find correct line in table above.
    sal_uInt16 nLine = GetPresetImageId( m_xWndPresets->GetSelectedItemId() ) - 1;

    // Apply all styles from the table
    forint nBorder = 0; nBorder < svx::FRAMEBORDERTYPE_COUNT; ++nBorder )
    {
        svx::FrameBorderType eBorder = svx::GetFrameBorderTypeFromIndex( nBorder );
        switch( ppeStates[ nLine ][ nBorder ] )
        {
            case SHOW:  m_aFrameSel.SelectBorder( eBorder );      break;
            case HIDE:  /* nothing to do */                     break;
            case DONT:  m_aFrameSel.SetBorderDontCare( eBorder ); break;
        }
    }

    // Show all lines that have been selected above
    if( m_aFrameSel.IsAnyBorderSelected() )
    {
        // any visible style, but "no-line" in line list box? -> use hair-line
        if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE)
            m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID);

        // set current style to all previously selected lines
        SelStyleHdl_Impl(*m_xLbLineStyle);
        SelColHdl_Impl(*m_xLbLineColor);
    }

    // Presets ValueSet does not show a selection (used as push buttons).
    m_xWndPresets->SetNoSelection();

    LinesChanged_Impl( nullptr );
    UpdateRemoveAdjCellBorderCB( nLine + 1 );
}

IMPL_LINK_NOARG(SvxBorderTabPage, SelSdwHdl_Impl, ValueSet*, void)
{
    bool bEnable = m_xWndShadows->GetSelectedItemId() > 1;
    m_xFtShadowSize->set_sensitive(bEnable);
    m_xEdShadowSize->set_sensitive(bEnable);
    m_xFtShadowColor->set_sensitive(bEnable);
    m_xLbShadowColor->set_sensitive(bEnable);
}

IMPL_LINK(SvxBorderTabPage, SelColHdl_Impl, ColorListBox&, rColorBox, void)
{
    const NamedColor& aNamedColor = rColorBox.GetSelectedEntry();
    m_aFrameSel.SetColorToSelection(aNamedColor.m_aColor, aNamedColor.getComplexColor());
}

IMPL_LINK_NOARG(SvxBorderTabPage, ModifyWidthLBHdl_Impl, weld::ComboBox&, void)
{
    sal_Int32 nPos = m_xLineWidthLB->get_active();
    sal_Int32 nRemovedType = 0;
    if (m_xLineWidthLB->get_values_changed_from_saved()) {
        nRemovedType = std::size(s_LineWidths) - m_xLineWidthLB->get_count();
    }

    SetLineWidth(s_LineWidths[nPos + nRemovedType], nRemovedType);

    // Call the spinner handler to trigger all related modifications
    ModifyWidthMFHdl_Impl(*m_xLineWidthMF);
}

IMPL_LINK_NOARG(SvxBorderTabPage, ModifyWidthMFHdl_Impl, weld::MetricSpinButton&,&nbsp;void)
{
    sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE);

    // for DOUBLE_THIN line style we cannot allow thinner line width then 1.10pt
    if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN)
        m_xLineWidthMF->set_min(110, FieldUnit::NONE);
    else
        m_xLineWidthMF->set_min(5, FieldUnit::NONE);

    nVal = static_cast<sal_Int64>(vcl::ConvertDoubleValue(
                nVal,
                m_xLineWidthMF->get_digits(),
                FieldUnit::POINT, MapUnit::MapTwip ));
    m_xLbLineStyle->SetWidth( nVal );

    m_aFrameSel.SetStyleToSelection( nVal,
        m_xLbLineStyle->GetSelectEntryStyle() );
}

IMPL_LINK_NOARG(SvxBorderTabPage, SelStyleHdl_Impl, SvtLineListBox&, void)
{
    sal_Int64 nOldWidth = m_xLineWidthMF->get_value(FieldUnit::NONE);

    // for DOUBLE_THIN line style we cannot allow thinner line width then 1.10pt
    if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN)
        m_xLineWidthMF->set_min(110, FieldUnit::NONE);
    else
        m_xLineWidthMF->set_min(5, FieldUnit::NONE);

    nOldWidth = static_cast<sal_Int64>(vcl::ConvertDoubleValue(
        nOldWidth,
        m_xLineWidthMF->get_digits(),
        FieldUnit::POINT,
        MapUnit::MapTwip));

    const sal_Int64 nOldMinWidth = lcl_GetMinLineWidth(m_aFrameSel.getCurrentStyleLineStyle());
    const sal_Int64 nNewMinWidth = lcl_GetMinLineWidth(m_xLbLineStyle->GetSelectEntryStyle());

    // auto change line-width if it doesn't correspond to minimal value
    // let's change only in case when user has not changed the line-width into some custom value
    sal_Int64 nNewWidth = (nOldMinWidth == nOldWidth) ? nNewMinWidth : nOldWidth;

    // if we had selected a predefined border width under SvxBorderLineWidth::Medium set the Medium as default
    // otherwise if we had a custom border width under 1.10pt then set the spinner to the maximum allowed value for double border styles
    bool bNewDoubleHairline = m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN && !m_xLineWidthMF->get_visible() &&
        (nOldWidth == SvxBorderLineWidth::Hairline || nOldWidth == SvxBorderLineWidth::VeryThin || nOldWidth == SvxBorderLineWidth::Thin);
    if (bNewDoubleHairline && nNewWidth < SvxBorderLineWidth::Medium)
        nNewWidth = SvxBorderLineWidth::Medium;

    // set value inside edit box
    if (nOldWidth != nNewWidth)
    {
        const sal_Int64 nNewWidthPt = static_cast<sal_Int64>(vcl::ConvertDoubleValue(
            nNewWidth,
            m_xLineWidthMF->get_digits(),
            MapUnit::MapTwip,
            FieldUnit::POINT));
        SetLineWidth(nNewWidthPt);
    }

    if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN)
    {
        for (size_t i = 0; i < 3; i++)
        {
            m_xLineWidthLB->save_values_by_id(OUString::number(i));
            m_xLineWidthLB->remove_id(OUString::number(i));
        }
        if (m_xLineWidthLB->get_active_id().isEmpty())
            m_xLineWidthLB->set_active_id(u"3"_ustr);
    }
    else
    {
        if (m_xLineWidthLB->get_values_changed_from_saved())
        {
            for (size_t i = 0; i < 3; i++)
                m_xLineWidthLB->append(i, OUString::number(i), m_xLineWidthLB->get_saved_values(i));
            m_xLineWidthLB->removeSavedValues();
        }
    }

    // set value inside style box
    m_aFrameSel.SetStyleToSelection( nNewWidth,
        m_xLbLineStyle->GetSelectEntryStyle() );
}


// ValueSet handling
sal_uInt16 SvxBorderTabPage::GetPresetImageId( sal_uInt16 nValueSetIdx ) const
{
    // table with all sets of predefined border styles
    static const sal_uInt16 ppnImgIds[][ BORDER_PRESET_COUNT ] =
    {
        // simple cell without diagonal frame borders
        {   IID_PRE_CELL_NONE,  IID_PRE_CELL_ALL,       IID_PRE_CELL_LR,        IID_PRE_CELL_TB,    IID_PRE_CELL_L          },
        // simple cell with diagonal frame borders
        {   IID_PRE_CELL_NONE,  IID_PRE_CELL_ALL,       IID_PRE_CELL_LR,        IID_PRE_CELL_TB,    IID_PRE_CELL_DIAG       },
        // with horizontal inner frame border
        {   IID_PRE_HOR_NONE,   IID_PRE_HOR_OUTER,      IID_PRE_HOR_HOR,        IID_PRE_HOR_ALL,    IID_PRE_HOR_OUTER2      },
        // with vertical inner frame border
        {   IID_PRE_VER_NONE,   IID_PRE_VER_OUTER,      IID_PRE_VER_VER,        IID_PRE_VER_ALL,    IID_PRE_VER_OUTER2      },
        // with horizontal and vertical inner frame borders
        {   IID_PRE_TABLE_NONE, IID_PRE_TABLE_OUTER,    IID_PRE_TABLE_OUTERH,   IID_PRE_TABLE_ALL,  IID_PRE_TABLE_OUTER2    }
    };

    // find correct set of presets
    int nLine = 0;
    if( !mbHorEnabled && !mbVerEnabled )
        nLine = (mbTLBREnabled || mbBLTREnabled) ? 1 : 0;
    else if( mbHorEnabled && !mbVerEnabled )
        nLine = 2;
    else if( !mbHorEnabled && mbVerEnabled )
        nLine = 3;
    else
        nLine = 4;

    DBG_ASSERT( (1 <= nValueSetIdx) && (nValueSetIdx <= BORDER_PRESET_COUNT),
        "SvxBorderTabPage::GetPresetImageId - wrong index" );
    return ppnImgIds[ nLine ][ nValueSetIdx - 1 ];
}

TranslateId SvxBorderTabPage::GetPresetStringId( sal_uInt16 nValueSetIdx ) const
{
    // string resource IDs for each image (in order of the IID_PRE_* image IDs)
    static const TranslateId pnStrIds[] =
    {
        RID_SVXSTR_TABLE_PRESET_NONE,
        RID_SVXSTR_PARA_PRESET_ALL,
        RID_SVXSTR_PARA_PRESET_ONLYLEFTRIGHT,
        RID_SVXSTR_PARA_PRESET_ONLYTOPBOTTOM,
        RID_SVXSTR_PARA_PRESET_ONLYLEFT,
        RID_SVXSTR_PARA_PRESET_DIAGONAL,

        RID_SVXSTR_TABLE_PRESET_NONE,
        RID_SVXSTR_TABLE_PRESET_ONLYOUTER,
        RID_SVXSTR_HOR_PRESET_ONLYHOR,
        RID_SVXSTR_TABLE_PRESET_OUTERALL,
        RID_SVXSTR_TABLE_PRESET_OUTERINNER,

        RID_SVXSTR_TABLE_PRESET_NONE,
        RID_SVXSTR_TABLE_PRESET_ONLYOUTER,
        RID_SVXSTR_VER_PRESET_ONLYVER,
        RID_SVXSTR_TABLE_PRESET_OUTERALL,
        RID_SVXSTR_TABLE_PRESET_OUTERINNER,

        RID_SVXSTR_TABLE_PRESET_NONE,
        RID_SVXSTR_TABLE_PRESET_ONLYOUTER,
        RID_SVXSTR_TABLE_PRESET_OUTERHORI,
        RID_SVXSTR_TABLE_PRESET_OUTERALL,
        RID_SVXSTR_TABLE_PRESET_OUTERINNER
    };
    return pnStrIds[ GetPresetImageId( nValueSetIdx ) - 1 ];
}

void SvxBorderTabPage::FillPresetVS()
{
    // basic initialization of the ValueSet
    m_xWndPresets->SetStyle( m_xWndPresets->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER );
    m_xWndPresets->SetColCount( BORDER_PRESET_COUNT );

    // insert images and help texts
    for( sal_uInt16 nVSIdx = 1; nVSIdx <= BORDER_PRESET_COUNT; ++nVSIdx )
    {
        m_xWndPresets->InsertItem( nVSIdx );
        m_xWndPresets->SetItemImage(nVSIdx, m_aBorderImgVec[GetPresetImageId(nVSIdx) - 1]);
        m_xWndPresets->SetItemText( nVSIdx, SvxResId( GetPresetStringId( nVSIdx ) ) );
    }

    // show the control
    m_xWndPresets->SetNoSelection();
    m_xWndPresets->SetOptimalSize();
    m_xWndPresets->Show();
}

void SvxBorderTabPage::FillShadowVS()
{
    // basic initialization of the ValueSet
    m_xWndShadows->SetStyle( m_xWndShadows->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER );
    m_xWndShadows->SetColCount( BORDER_SHADOW_COUNT );

    // string resource IDs for each image
    static const TranslateId pnStrIds[ BORDER_SHADOW_COUNT ] =
        { RID_CUISTR_SHADOW_STYLE_NONE, RID_CUISTR_SHADOW_STYLE_BOTTOMRIGHT, RID_CUISTR_SHADOW_STYLE_TOPRIGHT, RID_CUISTR_SHADOW_STYLE_BOTTOMLEFT, RID_CUISTR_SHADOW_STYLE_TOPLEFT };

    // insert images and help texts
    for( sal_uInt16 nVSIdx = 1; nVSIdx <= BORDER_SHADOW_COUNT; ++nVSIdx )
    {
        m_xWndShadows->InsertItem( nVSIdx );
        m_xWndShadows->SetItemImage(nVSIdx, m_aShadowImgVec[nVSIdx-1]);
        m_xWndShadows->SetItemText( nVSIdx, CuiResId( pnStrIds[ nVSIdx - 1 ] ) );
    }

    // show the control
    m_xWndShadows->SelectItem( 1 );
    m_xWndShadows->SetOptimalSize();
    m_xWndShadows->Show();
}


void SvxBorderTabPage::FillValueSets()
{
    FillPresetVS();
    FillShadowVS();
}

void SvxBorderTabPage::SetLineWidth( sal_Int64 nWidth, sal_Int32 nRemovedType )
{
    if ( nWidth >= 0 )
        m_xLineWidthMF->set_value( nWidth, FieldUnit::POINT );

    auto it = std::find( std::begin(s_LineWidths), std::end(s_LineWidths), nWidth );

    if ( it != std::end(s_LineWidths) && *it >= 0 )
    {
        // Select predefined value in combobox
        m_xLineWidthMF->hide();
        m_xLineWidthLB->set_active(std::distance(std::begin(s_LineWidths), it) - nRemovedType);
    }
    else
    {
        // This is not one of predefined values. Show spinner
        m_xLineWidthLB->set_active(std::size(s_LineWidths) - nRemovedType -1);
        m_xLineWidthMF->show();
    }
}

static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ )
{
    return SvxBorderLine::threeDMediumColor( aMain );
}

void SvxBorderTabPage::FillLineListBox_Impl()
{
    using namespace ::com::sun::star::table::BorderLineStyle;

    static struct {
        SvxBorderLineStyle mnStyle;
        SvtLineListBox::ColorFunc mpColor1Fn;
        SvtLineListBox::ColorFunc mpColor2Fn;
        SvtLineListBox::ColorDistFunc mpColorDistFn;
    } const aLines[] = {
        // Simple lines
        { SvxBorderLineStyle::SOLID,        &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::DOTTED,       &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::DASHED,       &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::FINE_DASHED,  &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::DASH_DOT,     &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::DASH_DOT_DOT, &sameColor, &sameColor, &sameDistColor },

        // Double lines
        { SvxBorderLineStyle::DOUBLE,              &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::DOUBLE_THIN,         &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::THINTHICK_SMALLGAP,  &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::THINTHICK_MEDIUMGAP, &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::THINTHICK_LARGEGAP,  &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::THICKTHIN_SMALLGAP,  &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::THICKTHIN_MEDIUMGAP, &sameColor, &sameColor, &sameDistColor },
        { SvxBorderLineStyle::THICKTHIN_LARGEGAP,  &sameColor, &sameColor, &sameDistColor },

        { SvxBorderLineStyle::EMBOSSED, &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, &lcl_mediumColor },
        { SvxBorderLineStyle::ENGRAVED, &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, &lcl_mediumColor },

        { SvxBorderLineStyle::OUTSET, &SvxBorderLine::lightColor, &SvxBorderLine::darkColor, &sameDistColor },
        { SvxBorderLineStyle::INSET,  &SvxBorderLine::darkColor, &SvxBorderLine::lightColor, &sameDistColor }
    };

    m_xLbLineStyle->SetSourceUnit( FieldUnit::TWIP );

    for (size_t i = 0; i < std::size(aLines); ++i)
    {
        if (!IsBorderLineStyleAllowed(aLines[i].mnStyle))
            continue;

        m_xLbLineStyle->InsertEntry(
            SvxBorderLine::getWidthImpl(aLines[i].mnStyle),
            aLines[i].mnStyle,
            lcl_GetMinLineWidth(aLines[i].mnStyle),
            aLines[i].mpColor1Fn,
            aLines[i].mpColor2Fn,
            aLines[i].mpColorDistFn);
    }

    sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE);
    nVal = static_cast<sal_Int64>(vcl::ConvertDoubleValue(nVal, m_xLineWidthMF->get_digits(),
                                                                  m_xLineWidthMF->get_unit(), MapUnit::MapTwip));
    m_xLbLineStyle->SetWidth( nVal );
}


IMPL_LINK_NOARG(SvxBorderTabPage, LinesChanged_Impl, LinkParamNone*, void)
{
    if (!mbUseMarginItem && m_xLeftMF->get_visible())
    {
        bool bLineSet = m_aFrameSel.IsAnyBorderVisible();
        bool bSpaceModified =   mbLeftModified ||
                                mbRightModified ||
                                mbTopModified ||
                                mbBottomModified;

        if(bLineSet)
        {
            if(!bSpaceModified)
            {
                m_xLeftMF->set_value(nMinValue, FieldUnit::NONE);
                m_xRightMF->set_value(nMinValue, FieldUnit::NONE);
                m_xTopMF->set_value(nMinValue, FieldUnit::NONE);
                m_xBottomMF->set_value(nMinValue, FieldUnit::NONE);
            }
        }
        else
        {
            m_xLeftMF->set_min(0, FieldUnit::NONE);
            m_xRightMF->set_min(0, FieldUnit::NONE);
            m_xTopMF->set_min(0, FieldUnit::NONE);
            m_xBottomMF->set_min(0, FieldUnit::NONE);
        }
        // for tables everything is allowed
        SvxBoxInfoItemValidFlags nValid = SvxBoxInfoItemValidFlags::TOP|SvxBoxInfoItemValidFlags::BOTTOM|SvxBoxInfoItemValidFlags::LEFT|SvxBoxInfoItemValidFlags::RIGHT;

        m_xLeftFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) );
        m_xRightFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) );
        m_xTopFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) );
        m_xBottomFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) );
        m_xLeftMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) );
        m_xRightMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) );
        m_xTopMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) );
        m_xBottomMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) );
        m_xSynchronizeCB->set_sensitive(m_xRightMF->get_sensitive() || m_xTopMF->get_sensitive() ||
                                        m_xBottomMF->get_sensitive() || m_xLeftMF->get_sensitive());
    }
    UpdateRemoveAdjCellBorderCB( SAL_MAX_UINT16 );
}


IMPL_LINK( SvxBorderTabPage, ModifyDistanceHdl_Impl, weld::MetricSpinButton&, rField, void)
{
    if (&rField == m_xLeftMF.get())
        mbLeftModified = true;
    else if (&rField == m_xRightMF.get())
        mbRightModified = true;
    else if (&rField == m_xTopMF.get())
        mbTopModified = true;
    else if (&rField == m_xBottomMF.get())
        mbBottomModified = true;

    if (mbSync)
    {
        const auto nVal = rField.get_value(FieldUnit::NONE);
        if (&rField != m_xLeftMF.get())
            m_xLeftMF->set_value(nVal, FieldUnit::NONE);
        if (&rField != m_xRightMF.get())
            m_xRightMF->set_value(nVal, FieldUnit::NONE);
        if (&rField != m_xTopMF.get())
            m_xTopMF->set_value(nVal, FieldUnit::NONE);
        if (&rField != m_xBottomMF.get())
            m_xBottomMF->set_value(nVal, FieldUnit::NONE);
    }
}

IMPL_LINK( SvxBorderTabPage, SyncHdl_Impl, weld::Toggleable&, rBox, void)
{
    mbSync = rBox.get_active();
}

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=95 G=94

¤ Dauer der Verarbeitung: 0.39 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.