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 59 kB image not shown  

Quelle  tpline.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 <memory>
#include <editeng/sizeitem.hxx>
#include <osl/file.hxx>
#include <tools/urlobj.hxx>

#include <strings.hrc>
#include <svx/colorbox.hxx>
#include <svx/dlgctrl.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlinjoit.hxx>
#include <svx/xlncapit.hxx>
#include <svx/xlndsit.hxx>
#include <svx/xlnwtit.hxx>
#include <svx/xlnstwit.hxx>
#include <svx/xlnedwit.hxx>
#include <svx/xlnclit.hxx>
#include <svx/xlnstit.hxx>
#include <svx/xlnedit.hxx>
#include <svx/xlnstcit.hxx>
#include <svx/xlnedcit.hxx>


#include <svx/tabline.hxx>
#include <svx/xtable.hxx>
#include <svx/drawitem.hxx>
#include <cuitabline.hxx>
#include <dialmgr.hxx>
#include <svx/dlgutil.hxx>
#include <svx/svxgraphicitem.hxx>
#include <svx/ofaitem.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdview.hxx>
#include <svx/svdmodel.hxx>
#include <svx/xlntrit.hxx>
#include <svx/xfltrit.hxx>
#include <editeng/numitem.hxx>
#include <editeng/brushitem.hxx>
#include <svx/gallery.hxx>
#include <sfx2/opengrf.hxx>
#include <svx/dialmgr.hxx>
#include <svx/svxids.hrc>
#include <svx/strings.hrc>
#include <cuitabarea.hxx>
#include <svtools/unitconv.hxx>
#include <comphelper/lok.hxx>
#include <o3tl/string_view.hxx>

#define MAX_BMP_WIDTH   16
#define MAX_BMP_HEIGHT  16

using namespace com::sun::star;

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

const WhichRangesContainer SvxLineTabPage::pLineRanges(svl::Items<
    XATTR_LINETRANSPARENCE, XATTR_LINETRANSPARENCE,
    SID_ATTR_LINE_STYLE, SID_ATTR_LINE_ENDCENTER
>);

SvxLineTabPage::SvxLineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
    : SfxTabPage(pPage, pController, u"cui/ui/linetabpage.ui"_ustr, u"LineTabPage"_ustr, &rInAttrs)
    , m_pSymbolList(nullptr)
    , m_bNewSize(false)
    , m_nSymbolType(SVX_SYMBOLTYPE_UNKNOWN) // unknown respectively unchanged
    , m_bLastWidthModified(false)
    , m_aSymbolLastSize(Size(0,0))
    , m_bSymbols(false)
    , m_rOutAttrs(rInAttrs)
    , m_bObjSelected(false)
    , m_aXLineAttr(rInAttrs.GetPool())
    , m_rXLSet(m_aXLineAttr.GetItemSet())
    , m_pnLineEndListState(nullptr)
    , m_pnDashListState(nullptr)
    , m_pnColorListState(nullptr)
    , m_nPageType(PageType::Area)
    , m_nDlgType(0)
    , m_pPosDashLb(nullptr)
    , m_pPosLineEndLb(nullptr)
    , m_xBoxColor(m_xBuilder->weld_widget(u"boxCOLOR"_ustr))
    , m_xLbLineStyle(new SvxLineLB(m_xBuilder->weld_combo_box(u"LB_LINE_STYLE"_ustr)))
    , m_xLbColor(new ColorListBox(m_xBuilder->weld_menu_button(u"LB_COLOR"_ustr),
                [this]{ return GetDialogController()->getDialog(); }))
    , m_xBoxWidth(m_xBuilder->weld_widget(u"boxWIDTH"_ustr))
    , m_xMtrLineWidth(m_xBuilder->weld_metric_spin_button(u"MTR_FLD_LINE_WIDTH"_ustr, FieldUnit::CM))
    , m_xBoxTransparency(m_xBuilder->weld_widget(u"boxTRANSPARENCY"_ustr))
    , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button(u"MTR_LINE_TRANSPARENT"_ustr, FieldUnit::PERCENT))
    , m_xFlLineEnds(m_xBuilder->weld_widget(u"FL_LINE_ENDS"_ustr))
    , m_xBoxArrowStyles(m_xBuilder->weld_widget(u"boxARROW_STYLES"_ustr))
    , m_xLbStartStyle(new SvxLineEndLB(m_xBuilder->weld_combo_box(u"LB_START_STYLE"_ustr)))
    , m_xBoxStart(m_xBuilder->weld_widget(u"boxSTART"_ustr))
    , m_xMtrStartWidth(m_xBuilder->weld_metric_spin_button(u"MTR_FLD_START_WIDTH"_ustr, FieldUnit::CM))
    , m_xTsbCenterStart(m_xBuilder->weld_check_button(u"TSB_CENTER_START"_ustr))
    , m_xBoxEnd(m_xBuilder->weld_widget(u"boxEND"_ustr))
    , m_xLbEndStyle(new SvxLineEndLB(m_xBuilder->weld_combo_box(u"LB_END_STYLE"_ustr)))
    , m_xMtrEndWidth(m_xBuilder->weld_metric_spin_button(u"MTR_FLD_END_WIDTH"_ustr, FieldUnit::CM))
    , m_xTsbCenterEnd(m_xBuilder->weld_check_button(u"TSB_CENTER_END"_ustr))
    , m_xCbxSynchronize(m_xBuilder->weld_check_button(u"CBX_SYNCHRONIZE"_ustr))
    , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, u"CTL_PREVIEW"_ustr, m_aCtlPreview))
    , m_xFLEdgeStyle(m_xBuilder->weld_widget(u"FL_EDGE_STYLE"_ustr))
    , m_xGridEdgeCaps(m_xBuilder->weld_widget(u"gridEDGE_CAPS"_ustr))
    , m_xLBEdgeStyle(m_xBuilder->weld_combo_box(u"LB_EDGE_STYLE"_ustr))
    , m_xLBCapStyle(m_xBuilder->weld_combo_box(u"LB_CAP_STYLE"_ustr)) // LineCaps
    , m_xFlSymbol(m_xBuilder->weld_widget(u"FL_SYMBOL_FORMAT"_ustr)) //#58425# Symbols on a line (e.g. StarChart)
    , m_xGridIconSize(m_xBuilder->weld_widget(u"gridICON_SIZE"_ustr))
    , m_xSymbolMB(m_xBuilder->weld_menu_button(u"MB_SYMBOL_BITMAP"_ustr))
    , m_xSymbolWidthMF(m_xBuilder->weld_metric_spin_button(u"MF_SYMBOL_WIDTH"_ustr, FieldUnit::CM))
    , m_xSymbolHeightMF(m_xBuilder->weld_metric_spin_button(u"MF_SYMBOL_HEIGHT"_ustr, FieldUnit::CM))
    , m_xSymbolRatioCB(m_xBuilder->weld_check_button(u"CB_SYMBOL_RATIO"_ustr))
{
    // This Page requires ExchangeSupport
    SetExchangeSupport();

    // Metric set
    FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs );

    switch ( eFUnit )
    {
        case FieldUnit::M:
        case FieldUnit::KM:
            eFUnit = FieldUnit::MM;
            [[fallthrough]]; // we now have mm
        case FieldUnit::MM:
            m_xMtrLineWidth->set_increments(50, 500, FieldUnit::NONE);
            m_xMtrStartWidth->set_increments(50, 500, FieldUnit::NONE);
            m_xMtrEndWidth->set_increments(50, 500, FieldUnit::NONE);
            break;

            case FieldUnit::INCH:
            m_xMtrLineWidth->set_increments(2, 20, FieldUnit::NONE);
            m_xMtrStartWidth->set_increments(2, 20, FieldUnit::NONE);
            m_xMtrEndWidth->set_increments(2, 20, FieldUnit::NONE);
            break;
            default: ;// prevent warning
    }
    SetFieldUnit( *m_xMtrLineWidth, eFUnit );
    SetFieldUnit( *m_xMtrStartWidth, eFUnit );
    SetFieldUnit( *m_xMtrEndWidth, eFUnit );

    // determine PoolUnit
    SfxItemPool* pPool = m_rOutAttrs.GetPool();
    assert(pPool && "Where is the pool?");
    m_ePoolUnit = pPool->GetMetric( SID_ATTR_LINE_WIDTH );

    m_xLbLineStyle->connect_changed(LINK(this, SvxLineTabPage, ClickInvisibleHdl_Impl));
    m_xLbColor->SetSelectHdl( LINK( this, SvxLineTabPage, ChangePreviewListBoxHdl_Impl ) );
    m_xMtrLineWidth->connect_value_changed(LINK(this, SvxLineTabPage, ChangePreviewModifyHdl_Impl));
    m_xMtrTransparent->connect_value_changed(LINK( this, SvxLineTabPage, ChangeTransparentHdl_Impl));

    m_xLbStartStyle->connect_changed(LINK(this, SvxLineTabPage, ChangeStartListBoxHdl_Impl));
    m_xLbEndStyle->connect_changed(LINK(this, SvxLineTabPage, ChangeEndListBoxHdl_Impl));
    m_xMtrStartWidth->connect_value_changed(LINK(this, SvxLineTabPage, ChangeStartModifyHdl_Impl));
    m_xMtrEndWidth->connect_value_changed(LINK( this, SvxLineTabPage, ChangeEndModifyHdl_Impl));
    m_xTsbCenterStart->connect_toggled(LINK(this, SvxLineTabPage, ChangeStartClickHdl_Impl));
    m_xTsbCenterEnd->connect_toggled(LINK(this, SvxLineTabPage, ChangeEndClickHdl_Impl));

    Link<weld::ComboBox&,void> aEdgeStyle = LINK(this, SvxLineTabPage, ChangeEdgeStyleHdl_Impl);
    m_xLBEdgeStyle->connect_changed(aEdgeStyle);

    // LineCaps
    Link<weld::ComboBox&,void> aCapStyle = LINK(this, SvxLineTabPage, ChangeCapStyleHdl_Impl);
    m_xLBCapStyle->connect_changed(aCapStyle);

    // Symbols on a line (eg star charts), MB-handler set
    m_xSymbolMB->connect_selected(LINK(this, SvxLineTabPage, GraphicHdl_Impl));
    m_xSymbolWidthMF->connect_value_changed(LINK(this, SvxLineTabPage, SizeHdl_Impl));
    m_xSymbolHeightMF->connect_value_changed(LINK(this, SvxLineTabPage, SizeHdl_Impl));
    m_xSymbolRatioCB->connect_toggled(LINK(this, SvxLineTabPage, RatioHdl_Impl));

    m_xSymbolRatioCB->set_active(true);
    ShowSymbolControls(false);

    m_nActLineWidth = -1;
}

void SvxLineTabPage::ShowSymbolControls(bool bOn)
{
    // Symbols on a line (e.g. StarCharts), symbol-enable controls

    m_bSymbols=bOn;
    m_xFlSymbol->set_visible(bOn);
    m_aCtlPreview.ShowSymbol(bOn);
}

SvxLineTabPage::~SvxLineTabPage()
{
    m_xCtlPreview.reset();
    m_xLbEndStyle.reset();
    m_xLbStartStyle.reset();
    m_xLbColor.reset();
    m_xLbLineStyle.reset();
    m_aGalleryBrushItems.clear();
    m_aSymbolBrushItems.clear();
}

void SvxLineTabPage::Construct()
{
    FillListboxes();
    PopulateMenus();
}

void SvxLineTabPage::FillListboxes()
{
    // Line styles
    auto nOldSelect = m_xLbLineStyle->get_active();
    // aLbLineStyle.FillStyles();
    m_xLbLineStyle->Fill( m_pDashList );
    m_xLbLineStyle->set_active( nOldSelect );

    // Line end style
    OUString sNone( comphelper::LibreOfficeKit::isActive() ? SvxResId( RID_SVXSTR_INVISIBLE )
        : SvxResId( RID_SVXSTR_NONE ) );
    nOldSelect = m_xLbStartStyle->get_active();
    m_xLbStartStyle->clear();
    m_xLbStartStyle->append_text(sNone);
    m_xLbStartStyle->Fill(m_pLineEndList);
    m_xLbStartStyle->set_active(nOldSelect);
    nOldSelect = m_xLbEndStyle->get_active();
    m_xLbEndStyle->clear();
    m_xLbEndStyle->append_text(sNone);
    m_xLbEndStyle->Fill(m_pLineEndList, false);
    m_xLbEndStyle->set_active(nOldSelect);
}

void SvxLineTabPage::ActivatePage( const SfxItemSet& rSet )
{
    const SfxUInt16Item* pPageTypeItem = rSet.GetItem<SfxUInt16Item>(SID_PAGE_TYPE, false);
    if (pPageTypeItem)
        SetPageType(static_cast<PageType>(pPageTypeItem->GetValue()));
    if( m_nDlgType == 0 && m_pDashList.is() )
    {
        sal_Int32 nPos;
        sal_Int32 nCount;

        // Dash list
        if( ( *m_pnDashListState & ChangeType::MODIFIED ) ||
            ( *m_pnDashListState & ChangeType::CHANGED ) )
        {
            if( *m_pnDashListState & ChangeType::CHANGED )
                m_pDashList = static_cast<SvxLineTabDialog*>(GetDialogController() )->GetNewDashList();

            *m_pnDashListState = ChangeType::NONE;

            // Style list
            nPos = m_xLbLineStyle->get_active();

            m_xLbLineStyle->clear();
            m_xLbLineStyle->append_text(SvxResId(RID_SVXSTR_INVISIBLE));
            m_xLbLineStyle->append_text(SvxResId(RID_SVXSTR_SOLID));
            m_xLbLineStyle->Fill(m_pDashList);
            nCount = m_xLbLineStyle->get_count();

            if ( nCount == 0 )
                ; // This case should never occur
            else if( nCount <= nPos )
                m_xLbLineStyle->set_active(0);
            else
                m_xLbLineStyle->set_active(nPos);
        }

        INetURLObject   aDashURL( m_pDashList->GetPath() );

        aDashURL.Append( m_pDashList->GetName() );
        DBG_ASSERT( aDashURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
        // LineEnd list
        if( ( *m_pnLineEndListState & ChangeType::MODIFIED ) || ( *m_pnLineEndListState & ChangeType::CHANGED ) )
        {
            if( *m_pnLineEndListState & ChangeType::CHANGED )
                m_pLineEndList = static_cast<SvxLineTabDialog*>(GetDialogController())->GetNewLineEndList();

            *m_pnLineEndListState = ChangeType::NONE;

            nPos = m_xLbLineStyle->get_active();
            OUString sNone( comphelper::LibreOfficeKit::isActive() ? SvxResId( RID_SVXSTR_INVISIBLE )
                : SvxResId( RID_SVXSTR_NONE ) );

            m_xLbStartStyle->clear();
            m_xLbStartStyle->append_text(sNone);

            m_xLbStartStyle->Fill( m_pLineEndList );
            nCount = m_xLbStartStyle->get_count();
            if( nCount == 0 )
                ; // This case should never occur
            else if( nCount <= nPos )
                m_xLbStartStyle->set_active(0);
            else
                m_xLbStartStyle->set_active(nPos);

            m_xLbEndStyle->clear();
            m_xLbEndStyle->append_text(sNone);

            m_xLbEndStyle->Fill( m_pLineEndList, false );
            nCount = m_xLbEndStyle->get_count();

            if( nCount == 0 )
                ; // This case should never occur
            else if( nCount <= nPos )
                m_xLbEndStyle->set_active(0);
            else
                m_xLbEndStyle->set_active(nPos);
        }
        INetURLObject aLineURL( m_pLineEndList->GetPath() );

        aLineURL.Append( m_pLineEndList->GetName() );
        DBG_ASSERT( aLineURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
        // Evaluate if another TabPage set another fill type
        if( m_xLbLineStyle->get_active() != 0 )
        {
            if( m_nPageType == PageType::Hatch ) // 1
            {
                m_xLbLineStyle->set_active(*m_pPosDashLb + 2); // +2 due to SOLID and INVISIBLE
                ChangePreviewHdl_Impl( nullptr );
            }
            if( m_nPageType == PageType::Bitmap )
            {
                m_xLbStartStyle->set_active(*m_pPosLineEndLb + 1);// +1 due to SOLID
                m_xLbEndStyle->set_active(*m_pPosLineEndLb + 1);// +1 due to SOLID
                ChangePreviewHdl_Impl( nullptr );
            }
        }

            // ColorList
        if( *m_pnColorListState != ChangeType::NONE )
        {
            ChangePreviewHdl_Impl( nullptr );
        }

        m_nPageType = PageType::Area;
    }
    // Page does not yet exist in the ctor, that's why we do it here!

    else if (m_nDlgType == 1101) // nNoArrowNoShadowDlg from chart2/source/controller/dialogs/dlg_ObjectProperties.cxx
    {
        m_xFlLineEnds->hide();
        m_xFLEdgeStyle->hide();
    }
}


DeactivateRC SvxLineTabPage::DeactivatePage( SfxItemSet* _pSet )
{
    if( m_nDlgType == 0 ) // Line dialog
    {
        m_nPageType = PageType::Gradient; // possibly for extensions
        *m_pPosDashLb = m_xLbLineStyle->get_active() - 2;// First entry SOLID!!!
        sal_Int32 nPos = m_xLbStartStyle->get_active();
        if (nPos != -1)
            nPos--;
        *m_pPosLineEndLb = nPos;
    }

    if( _pSet )
        FillItemSet( _pSet );

    return DeactivateRC::LeavePage;
}


bool SvxLineTabPage::FillItemSet( SfxItemSet* rAttrs )
{
    const SfxPoolItem* pOld = nullptr;
    sal_Int32  nPos;
    bool    bModified = false;

    // To prevent modifications to the list, we do not set other page's items.
    if( m_nDlgType != 0 || m_nPageType != PageType::Hatch )
    {
        nPos = m_xLbLineStyle->get_active();
        if( nPos != -1 &&
            m_xLbLineStyle->get_value_changed_from_saved() )
        {
            std::unique_ptr<XLineStyleItem> pStyleItem;

            if( nPos == 0 )
                pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_NONE ));
            else if( nPos == 1 )
                pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_SOLID ));
            else
            {
                pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_DASH ));

                // For added security
                if( m_pDashList->Count() > static_cast<tools::Long>( nPos - 2 ) )
                {
                    XLineDashItem aDashItem( m_xLbLineStyle->get_active_text(),
                                        m_pDashList->GetDash( nPos - 2 )->GetDash() );
                    pOld = GetOldItem( *rAttrs, XATTR_LINEDASH );
                    if ( !pOld || !( *static_cast<const XLineDashItem*>(pOld) == aDashItem ) )
                    {
                        rAttrs->Put( aDashItem );
                        bModified = true;
                    }
                }
            }
            pOld = GetOldItem( *rAttrs, XATTR_LINESTYLE );
            if ( !pOld || !( *static_cast<const XLineStyleItem*>(pOld) == *pStyleItem ) )
            {
                rAttrs->Put( std::move(pStyleItem) );
                bModified = true;
            }
        }
    }
    // Line width
    // GetSavedValue() returns OUString!
    if( m_xMtrLineWidth->get_value_changed_from_saved() )
    {
        XLineWidthItem aItem( GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ) );
        pOld = GetOldItem( *rAttrs, XATTR_LINEWIDTH );
        if ( !pOld || !( *static_cast<const XLineWidthItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }
    // Width line start
    if( m_xMtrStartWidth->get_value_changed_from_saved() )
    {
        XLineStartWidthItem aItem( GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ) );
        pOld = GetOldItem( *rAttrs, XATTR_LINESTARTWIDTH );
        if ( !pOld || !( *static_cast<const XLineStartWidthItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }
    // Width line end
    if( m_xMtrEndWidth->get_value_changed_from_saved() )
    {
        XLineEndWidthItem aItem( GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ) );
        pOld = GetOldItem( *rAttrs, XATTR_LINEENDWIDTH );
        if ( !pOld || !( *static_cast<const XLineEndWidthItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }

    // Line color
    if (m_xLbColor->IsValueChangedFromSaved())
    {
        NamedColor aNamedColor = m_xLbColor->GetSelectedEntry();
        XLineColorItem aItem(aNamedColor.m_aName, aNamedColor.m_aColor);
        aItem.setComplexColor(aNamedColor.getComplexColor());

        pOld = GetOldItem( *rAttrs, XATTR_LINECOLOR );
        if ( !pOld || !( *static_cast<const XLineColorItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }

    if( m_nDlgType != 0 || m_nPageType != PageType::Bitmap )
    {
        // Line start
        nPos = m_xLbStartStyle->get_active();
        if( nPos != -1 && m_xLbStartStyle->get_value_changed_from_saved() )
        {
            std::unique_ptr<XLineStartItem> pItem;
            if( nPos == 0 )
                pItem.reset(new XLineStartItem());
            else if( m_pLineEndList->Count() > static_cast<tools::Long>( nPos - 1 ) )
                pItem.reset(new XLineStartItem( m_xLbStartStyle->get_active_text(), m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ));
            pOld = GetOldItem( *rAttrs, XATTR_LINESTART );
            if( pItem && ( !pOld || *pOld != *pItem ) )
            {
                rAttrs->Put( std::move(pItem) );
                bModified = true;
            }
        }
        // Line end
        nPos = m_xLbEndStyle->get_active();
        if( nPos != -1 && m_xLbEndStyle->get_value_changed_from_saved() )
        {
            std::unique_ptr<XLineEndItem> pItem;
            if( nPos == 0 )
                pItem.reset(new XLineEndItem());
            else if( m_pLineEndList->Count() > static_cast<tools::Long>( nPos - 1 ) )
                pItem.reset(new XLineEndItem( m_xLbEndStyle->get_active_text(), m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ));
            pOld = GetOldItem( *rAttrs, XATTR_LINEEND );
            if( pItem &&
                ( !pOld || !( *static_cast<const XLineEndItem*>(pOld) == *pItem ) ) )
            {
                rAttrs->Put( std::move(pItem) );
                bModified = true;
            }
        }
    }

    // Centered line end
    TriState eState = m_xTsbCenterStart->get_state();
    if( m_xTsbCenterStart->get_state_changed_from_saved() )
    {
        XLineStartCenterItem aItem( eState != TRISTATE_FALSE );
        pOld = GetOldItem( *rAttrs, XATTR_LINESTARTCENTER );
        if ( !pOld || !( *static_cast<const XLineStartCenterItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }
    eState = m_xTsbCenterEnd->get_state();
    if( m_xTsbCenterEnd->get_state_changed_from_saved() )
    {
        XLineEndCenterItem aItem( eState != TRISTATE_FALSE );
        pOld = GetOldItem( *rAttrs, XATTR_LINEENDCENTER );
        if ( !pOld || !( *static_cast<const XLineEndCenterItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }

    // Transparency
    sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT);
    if( m_xMtrTransparent->get_value_changed_from_saved() )
    {
        XLineTransparenceItem aItem( nVal );
        pOld = GetOldItem( *rAttrs, XATTR_LINETRANSPARENCE );
        if ( !pOld || !( *static_cast<const XLineTransparenceItem*>(pOld) == aItem ) )
        {
            rAttrs->Put( aItem );
            bModified = true;
        }
    }

    nPos = m_xLBEdgeStyle->get_active();
    if (nPos != -1 && m_xLBEdgeStyle->get_value_changed_from_saved())
    {
        std::unique_ptr<XLineJointItem> pNew;

        switch(nPos)
        {
            case 0: // Rounded, default
            {
                pNew.reset(new XLineJointItem(css::drawing::LineJoint_ROUND));
                break;
            }
            case 1: // - none -
            {
                pNew.reset(new XLineJointItem(css::drawing::LineJoint_NONE));
                break;
            }
            case 2: // Miter
            {
                pNew.reset(new XLineJointItem(css::drawing::LineJoint_MITER));
                break;
            }
            case 3: // Bevel
            {
                pNew.reset(new XLineJointItem(css::drawing::LineJoint_BEVEL));
                break;
            }
        }

        if(pNew)
        {
            pOld = GetOldItem( *rAttrs, XATTR_LINEJOINT );

            if(!pOld || !(*static_cast<const XLineJointItem*>(pOld) == *pNew))
            {
                rAttrs->Put( std::move(pNew) );
                bModified = true;
            }
        }
    }

    // LineCaps
    nPos = m_xLBCapStyle->get_active();
    if (nPos != -1 && m_xLBCapStyle->get_value_changed_from_saved())
    {
        std::unique_ptr<XLineCapItem> pNew;

        switch(nPos)
        {
            case 0: // Butt (=Flat), default
            {
                pNew.reset(new XLineCapItem(css::drawing::LineCap_BUTT));
                break;
            }
            case 1: // Round
            {
                pNew.reset(new XLineCapItem(css::drawing::LineCap_ROUND));
                break;
            }
            case 2: // Square
            {
                pNew.reset(new XLineCapItem(css::drawing::LineCap_SQUARE));
                break;
            }
        }

        if(pNew)
        {
            pOld = GetOldItem( *rAttrs, XATTR_LINECAP );

            if(!pOld || !(*static_cast<const XLineCapItem*>(pOld) == *pNew))
            {
                rAttrs->Put( std::move(pNew) );
                bModified = true;
            }
        }
    }

    if(m_nSymbolType!=SVX_SYMBOLTYPE_UNKNOWN || m_bNewSize)
    {
        // Was set by selection or the size is different
        SvxSizeItem  aSItem(rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_SYMBOLSIZE),m_aSymbolSize);
        const SfxPoolItem* pSOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_SYMBOLSIZE) );
        m_bNewSize  = pSOld ? *static_cast<const SvxSizeItem *>(pSOld) != aSItem : m_bNewSize ;
        if(m_bNewSize)
        {
            rAttrs->Put(aSItem);
            bModified=true;
        }

        SfxInt32Item aTItem(rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_SYMBOLTYPE),m_nSymbolType);
        const SfxPoolItem* pTOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_SYMBOLTYPE) );
        bool bNewType = pTOld == nullptr || *static_cast<const SfxInt32Item*>(pTOld) != aTItem;
        if(bNewType && m_nSymbolType==SVX_SYMBOLTYPE_UNKNOWN)
            bNewType=false// a small fix, type wasn't set -> don't create a type item after all!
        if(bNewType)
        {
            rAttrs->Put(aTItem);
            bModified=true;
        }

        if(m_nSymbolType!=SVX_SYMBOLTYPE_NONE)
        {
            SvxBrushItem aBItem(m_aSymbolGraphic,GPOS_MM,rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_BRUSH));
            const SfxPoolItem* pBOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_BRUSH) );
            bool bNewBrush =
                pBOld == nullptr || *static_cast<const SvxBrushItem*>(pBOld) != aBItem;
            if(bNewBrush)
            {
                rAttrs->Put(aBItem);
                bModified=true;
            }
        }
    }
    rAttrs->Put (CntUInt16Item(SID_PAGE_TYPE, static_cast<sal_uInt16>(m_nPageType)));
    return bModified;
}


void SvxLineTabPage::FillXLSet_Impl()
{
    sal_Int32 nPos;

    if (m_xLbLineStyle->get_active() == -1)
    {
        m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
    }
    else if (m_xLbLineStyle->get_active() == 0)
        m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
    else if (m_xLbLineStyle->get_active() == 1)
        m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) );
    else
    {
        m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) );

        nPos = m_xLbLineStyle->get_active();
        if (nPos != -1)
        {
            m_rXLSet.Put( XLineDashItem( m_xLbLineStyle->get_active_text(),
                            m_pDashList->GetDash( nPos - 2 )->GetDash() ) );
        }
    }

    nPos = m_xLbStartStyle->get_active();
    if (nPos != -1)
    {
        if( nPos == 0 )
            m_rXLSet.Put( XLineStartItem() );
        else
            m_rXLSet.Put( XLineStartItem( m_xLbStartStyle->get_active_text(),
                        m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ) );
    }
    nPos = m_xLbEndStyle->get_active();
    if (nPos != -1)
    {
        if( nPos == 0 )
            m_rXLSet.Put( XLineEndItem() );
        else
            m_rXLSet.Put( XLineEndItem( m_xLbEndStyle->get_active_text(),
                        m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ) );
    }

    nPos = m_xLBEdgeStyle->get_active();
    if (nPos != -1)
    {
        switch(nPos)
        {
            case 0: // Rounded, default
            {
                m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_ROUND));
                break;
            }
            case 1: // - none -
            {
                m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_NONE));
                break;
            }
            case 2: // Miter
            {
                m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_MITER));
                break;
            }
            case 3: // Bevel
            {
                m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
                break;
            }
        }
    }

    // LineCaps
    nPos = m_xLBCapStyle->get_active();
    if (nPos != -1)
    {
        switch(nPos)
        {
            case 0: // Butt (=Flat), default
            {
                m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_BUTT));
                break;
            }
            case 1: // Round
            {
                m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_ROUND));
                break;
            }
            case 2: // Square
            {
                m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_SQUARE));
                break;
            }
        }
    }

    m_rXLSet.Put( XLineStartWidthItem( GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ) ) );
    m_rXLSet.Put( XLineEndWidthItem( GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ) ) );

    m_rXLSet.Put( XLineWidthItem( GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ) ) );
    NamedColor aNamedColor = m_xLbColor->GetSelectedEntry();
    XLineColorItem aLineColor(aNamedColor.m_aName, aNamedColor.m_aColor);
    aLineColor.setComplexColor(aNamedColor.getComplexColor());
    m_rXLSet.Put(aLineColor);

    // Centered line end
    if( m_xTsbCenterStart->get_state() == TRISTATE_TRUE )
        m_rXLSet.Put( XLineStartCenterItem( true ) );
    else if( m_xTsbCenterStart->get_state() == TRISTATE_FALSE )
        m_rXLSet.Put( XLineStartCenterItem( false ) );

    if( m_xTsbCenterEnd->get_state() == TRISTATE_TRUE )
        m_rXLSet.Put( XLineEndCenterItem( true ) );
    else if( m_xTsbCenterEnd->get_state() == TRISTATE_FALSE )
        m_rXLSet.Put( XLineEndCenterItem( false ) );

    // Transparency
    sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT);
    m_rXLSet.Put( XLineTransparenceItem( nVal ) );

    m_aCtlPreview.SetLineAttributes(m_aXLineAttr.GetItemSet());
}


void SvxLineTabPage::Reset( const SfxItemSet* rAttrs )
{
    drawing::LineStyle  eXLS; // drawing::LineStyle_NONE, drawing::LineStyle_SOLID, drawing::LineStyle_DASH

    // Line style
    tools::Long nSymType=SVX_SYMBOLTYPE_UNKNOWN;
    bool bPrevSym=false;
    bool bEnable=true;
    bool bIgnoreGraphic=false;
    bool bIgnoreSize=false;
    if(const SfxInt32Item* pSymbolTypeItem = rAttrs->GetItemIfSet(rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_SYMBOLTYPE)))
    {
        nSymType = pSymbolTypeItem->GetValue();
    }

    if(nSymType == SVX_SYMBOLTYPE_AUTO)
    {
        m_aSymbolGraphic=m_aAutoSymbolGraphic;
        m_aSymbolSize=m_aSymbolLastSize=m_aAutoSymbolGraphic.GetPrefSize();
        bPrevSym=true;
    }
    else if(nSymType == SVX_SYMBOLTYPE_NONE)
    {
        bEnable=false;
        bIgnoreGraphic=true;
        bIgnoreSize=true;
    }
    else if(nSymType >= 0)
    {
        ScopedVclPtrInstance< VirtualDevice > pVDev;
        pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));

        std::unique_ptr<SdrModel> pModel(
            new SdrModel(nullptr, nullptr, true));
        rtl::Reference<SdrPage> pPage = new SdrPage( *pModel, false );
        pPage->SetSize(Size(1000,1000));
        pModel->InsertPage( pPage.get(), 0 );
        {
        SdrView aView( *pModel, pVDev );
        aView.hideMarkHandles();
        aView.ShowSdrPage(pPage.get());
        size_t nSymTmp = static_cast<size_t>(nSymType);
        if(m_pSymbolList)
        {
            if(m_pSymbolList->GetObjCount())
            {
                nSymTmp %= m_pSymbolList->GetObjCount(); // Treat list as cyclic!
                rtl::Reference<SdrObject> pObj=m_pSymbolList->GetObj(nSymTmp);
                if(pObj)
                {
                    // directly clone to target SdrModel
                    pObj = pObj->CloneSdrObject(*pModel);

                    if(m_xSymbolAttr)
                    {
                        pObj->SetMergedItemSet(*m_xSymbolAttr);
                    }
                    else
                    {
                        pObj->SetMergedItemSet(m_rOutAttrs);
                    }

                    pPage->NbcInsertObject(pObj.get());

                    // Generate invisible square to give all symbol types a
                    // bitmap size, which is independent from specific glyph
                    rtl::Reference<SdrObject> pInvisibleSquare(m_pSymbolList->GetObj(0));

                    // directly clone to target SdrModel
                    pInvisibleSquare = pInvisibleSquare->CloneSdrObject(*pModel);

                    pPage->NbcInsertObject(pInvisibleSquare.get());
                    pInvisibleSquare->SetMergedItem(XFillTransparenceItem(100));
                    pInvisibleSquare->SetMergedItem(XLineTransparenceItem(100));

                    aView.MarkAll();
                    GDIMetaFile aMeta(aView.GetMarkedObjMetaFile());

                    m_aSymbolGraphic=Graphic(aMeta);
                    m_aSymbolSize=pObj->GetSnapRect().GetSize();
                    m_aSymbolGraphic.SetPrefSize(pInvisibleSquare->GetSnapRect().GetSize());
                    m_aSymbolGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
                    bPrevSym=true;
                    bEnable=true;
                    bIgnoreGraphic=true;

                    aView.UnmarkAll();
                    pPage->RemoveObject(1);
                    pInvisibleSquare.clear();
                    pPage->RemoveObject(0);
                    pObj.clear();
                }
            }
        }
        }
    }
    if(const SvxBrushItem* pBrushItem = rAttrs->GetItemIfSet(rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_BRUSH)))
    {
        const Graphic* pGraphic = pBrushItem->GetGraphic();
        if( pGraphic )
        {
            if(!bIgnoreGraphic)
            {
                m_aSymbolGraphic=*pGraphic;
            }
            if(!bIgnoreSize)
            {
                m_aSymbolSize=OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
                                                        pGraphic->GetPrefMapMode(),
                                                        MapMode(MapUnit::Map100thMM));
            }
            bPrevSym=true;
        }
    }

    if(const SvxSizeItem* pSymbolSizeItem = rAttrs->GetItemIfSet(rAttrs->GetPool()->GetWhichIDFromSlotID(SID_ATTR_SYMBOLSIZE)))
    {
        m_aSymbolSize = pSymbolSizeItem->GetSize();
    }

    m_xGridIconSize->set_sensitive(bEnable);

    if(bPrevSym)
    {
        SetMetricValue(*m_xSymbolWidthMF,  m_aSymbolSize.Width(), m_ePoolUnit);
        SetMetricValue(*m_xSymbolHeightMF, m_aSymbolSize.Height(),m_ePoolUnit);
        m_aCtlPreview.SetSymbol(&m_aSymbolGraphic,m_aSymbolSize);
        m_aSymbolLastSize=m_aSymbolSize;
    }

    if( rAttrs->GetItemState( XATTR_LINESTYLE ) != SfxItemState::INVALID )
    {
        eXLS = rAttrs->Get( XATTR_LINESTYLE ).GetValue();

        switch( eXLS )
        {
            case drawing::LineStyle_NONE:
                m_xLbLineStyle->set_active(0);
                break;
            case drawing::LineStyle_SOLID:
                m_xLbLineStyle->set_active(1);
                break;

            case drawing::LineStyle_DASH:
                m_xLbLineStyle->set_active(-1);
                m_xLbLineStyle->set_active_text(rAttrs->Get( XATTR_LINEDASH ).GetName());
                break;

            default:
                break;
        }
    }
    else
    {
        m_xLbLineStyle->set_active(-1);
    }

    // Line strength
    if( rAttrs->GetItemState( XATTR_LINEWIDTH ) != SfxItemState::INVALID )
    {
        SetMetricValue( *m_xMtrLineWidth, rAttrs->Get( XATTR_LINEWIDTH ).GetValue(), m_ePoolUnit );
    }
    else
        m_xMtrLineWidth->set_text(u""_ustr);

    // Line color
    m_xLbColor->SetNoSelection();

    if ( rAttrs->GetItemState( XATTR_LINECOLOR ) != SfxItemState::INVALID )
    {
        Color aCol = rAttrs->Get( XATTR_LINECOLOR ).GetColorValue();
        m_xLbColor->SelectEntry( aCol );
    }

    // Line start
    if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTART ) == SfxItemState::DEFAULT )
    {
        m_xLbStartStyle->set_sensitive(false);
    }
    else if( rAttrs->GetItemState( XATTR_LINESTART ) != SfxItemState::INVALID )
    {
        // #86265# select entry using list and polygon, not string
        bool bSelected(false);
        const basegfx::B2DPolyPolygon& rItemPolygon = rAttrs->Get(XATTR_LINESTART).GetLineStartValue();

        for(tools::Long a(0);!bSelected &&  a < m_pLineEndList->Count(); a++)
        {
            const XLineEndEntry* pEntry = m_pLineEndList->GetLineEnd(a);
            const basegfx::B2DPolyPolygon& rEntryPolygon = pEntry->GetLineEnd();

            if(rItemPolygon == rEntryPolygon)
            {
                // select this entry
                m_xLbStartStyle->set_active(a + 1);
                bSelected = true;
            }
        }

        if(!bSelected)
            m_xLbStartStyle->set_active(0);
    }
    else
    {
        m_xLbStartStyle->set_active(-1);
    }

    // Line end
    if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEEND ) == SfxItemState::DEFAULT )
    {
        m_xLbEndStyle->set_sensitive(false);
    }
    else if( rAttrs->GetItemState( XATTR_LINEEND ) != SfxItemState::INVALID )
    {
        // #86265# select entry using list and polygon, not string
        bool bSelected(false);
        const basegfx::B2DPolyPolygon& rItemPolygon = rAttrs->Get(XATTR_LINEEND).GetLineEndValue();

        for(tools::Long a(0);!bSelected &&  a < m_pLineEndList->Count(); a++)
        {
            const XLineEndEntry* pEntry = m_pLineEndList->GetLineEnd(a);
            const basegfx::B2DPolyPolygon& rEntryPolygon = pEntry->GetLineEnd();

            if(rItemPolygon == rEntryPolygon)
            {
                // select this entry
                m_xLbEndStyle->set_active(a + 1);
                bSelected = true;
            }
        }

        if(!bSelected)
            m_xLbEndStyle->set_active(0);
    }
    else
    {
        m_xLbEndStyle->set_active(-1);
    }

    // Line start strength
    if( m_bObjSelected &&  rAttrs->GetItemState( XATTR_LINESTARTWIDTH ) == SfxItemState::DEFAULT )
    {
        m_xMtrStartWidth->set_sensitive(false);
    }
    else if( rAttrs->GetItemState( XATTR_LINESTARTWIDTH ) != SfxItemState::INVALID )
    {
        SetMetricValue( *m_xMtrStartWidth,
                        rAttrs->Get( XATTR_LINESTARTWIDTH ).GetValue(),
                        m_ePoolUnit );
    }
    else
        m_xMtrStartWidth->set_text( u""_ustr );

    // Line end strength
    if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEENDWIDTH ) == SfxItemState::DEFAULT )
    {
        m_xMtrEndWidth->set_sensitive(false);
    }
    else if( rAttrs->GetItemState( XATTR_LINEENDWIDTH ) != SfxItemState::INVALID )
    {
        SetMetricValue( *m_xMtrEndWidth,
                        rAttrs->Get( XATTR_LINEENDWIDTH ).GetValue(),
                        m_ePoolUnit );
    }
    else
        m_xMtrEndWidth->set_text(u""_ustr);

    // Centered line end (start)
    if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTARTCENTER ) == SfxItemState::DEFAULT )
    {
        m_xTsbCenterStart->set_sensitive(false);
    }
    else if( rAttrs->GetItemState( XATTR_LINESTARTCENTER ) != SfxItemState::INVALID )
    {
        if( rAttrs->Get( XATTR_LINESTARTCENTER ).GetValue() )
            m_xTsbCenterStart->set_state(TRISTATE_TRUE);
        else
            m_xTsbCenterStart->set_state(TRISTATE_FALSE);
    }
    else
    {
        m_xTsbCenterStart->set_state(TRISTATE_INDET);
    }

    // Centered line end (end)
    if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEENDCENTER ) == SfxItemState::DEFAULT )
    {
        m_xTsbCenterEnd->set_sensitive(false);
    }
    else if( rAttrs->GetItemState( XATTR_LINEENDCENTER ) != SfxItemState::INVALID )
    {
        if( rAttrs->Get( XATTR_LINEENDCENTER ).GetValue() )
            m_xTsbCenterEnd->set_state(TRISTATE_TRUE);
        else
            m_xTsbCenterEnd->set_state(TRISTATE_FALSE);
    }
    else
    {
        m_xTsbCenterEnd->set_state(TRISTATE_INDET);
    }

    // Transparency
    if( rAttrs->GetItemState( XATTR_LINETRANSPARENCE ) != SfxItemState::INVALID )
    {
        sal_uInt16 nTransp = rAttrs->Get( XATTR_LINETRANSPARENCE ).GetValue();
        m_xMtrTransparent->set_value(nTransp, FieldUnit::PERCENT);
        ChangeTransparentHdl_Impl(*m_xMtrTransparent);
    }
    else
        m_xMtrTransparent->set_text( u""_ustr );

    if( !m_xLbStartStyle->get_sensitive()  &&
        !m_xLbEndStyle->get_sensitive()    &&
        !m_xMtrStartWidth->get_sensitive() &&
        !m_xMtrEndWidth->get_sensitive()   &&
        !m_xTsbCenterStart->get_sensitive()&&
        !m_xTsbCenterEnd->get_sensitive() )
    {
        m_xCbxSynchronize->set_sensitive(false);
        m_xFlLineEnds->set_sensitive(false);
    }

    // Synchronize
    // We get the value from the INI file now
    OUString aStr = GetUserData();
    m_xCbxSynchronize->set_active(aStr.toInt32() != 0);

    if(m_bObjSelected && SfxItemState::DEFAULT == rAttrs->GetItemState(XATTR_LINEJOINT))
    {
//         maFTEdgeStyle.set_sensitive(false);
        m_xLBEdgeStyle->set_sensitive(false);
    }
    else if(SfxItemState::INVALID != rAttrs->GetItemState(XATTR_LINEJOINT))
    {
        const css::drawing::LineJoint eLineJoint = rAttrs->Get(XATTR_LINEJOINT).GetValue();

        switch(eLineJoint)
        {
            case css::drawing::LineJoint::LineJoint_MAKE_FIXED_SIZE: // fallback to round, unused value
            case css::drawing::LineJoint_ROUND : m_xLBEdgeStyle->set_active(0); break;
            case css::drawing::LineJoint_NONE : m_xLBEdgeStyle->set_active(1); break;
            case css::drawing::LineJoint_MIDDLE : // fallback to mitre, unused value
            case css::drawing::LineJoint_MITER : m_xLBEdgeStyle->set_active(2); break;
            case css::drawing::LineJoint_BEVEL : m_xLBEdgeStyle->set_active(3); break;
        }
    }
    else
    {
        m_xLBEdgeStyle->set_active(-1);
    }

    // fdo#43209
    if(m_bObjSelected && SfxItemState::DEFAULT == rAttrs->GetItemState(XATTR_LINECAP))
    {
        m_xLBCapStyle->set_sensitive(false);
    }
    else if(SfxItemState::INVALID != rAttrs->GetItemState(XATTR_LINECAP))
    {
        const css::drawing::LineCap eLineCap(rAttrs->Get(XATTR_LINECAP).GetValue());

        switch(eLineCap)
        {
            case css::drawing::LineCap_ROUND: m_xLBCapStyle->set_active(1); break;
            case css::drawing::LineCap_SQUARE : m_xLBCapStyle->set_active(2); break;
            default /*css::drawing::LineCap_BUTT*/: m_xLBCapStyle->set_active(0); break;
        }
    }
    else
    {
        m_xLBCapStyle->set_active(-1);
    }

    // Save values
    m_xLbLineStyle->save_value();
    m_xMtrLineWidth->save_value();
    m_xLbColor->SaveValue();
    m_xLbStartStyle->save_value();
    m_xLbEndStyle->save_value();
    m_xMtrStartWidth->save_value();
    m_xMtrEndWidth->save_value();
    m_xTsbCenterStart->save_state();
    m_xTsbCenterEnd->save_state();
    m_xMtrTransparent->save_value();

    m_xLBEdgeStyle->save_value();

    // LineCaps
    m_xLBCapStyle->save_value();

    ClickInvisibleHdl_Impl();

    ChangePreviewHdl_Impl( nullptr );
}

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

IMPL_LINK_NOARG(SvxLineTabPage, ChangePreviewListBoxHdl_Impl, ColorListBox&, void)
{
    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK(SvxLineTabPage, ChangePreviewModifyHdl_Impl, weld::MetricSpinButton&, rEdit, void)
{
    ChangePreviewHdl_Impl(&rEdit);
}

void SvxLineTabPage::ChangePreviewHdl_Impl(const weld::MetricSpinButton* pCntrl)
{
    if (pCntrl == m_xMtrLineWidth.get())
    {
        // Line width and start end width
        sal_Int32 nNewLineWidth = GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit );
        if(m_nActLineWidth == -1)
        {
            // Don't initialize yet, get the start value
            const SfxPoolItem* pOld = GetOldItem( m_rXLSet, XATTR_LINEWIDTH );
            sal_Int32 nStartLineWidth = 0;
            if(pOld)
                nStartLineWidth = static_cast<const XLineWidthItem *>(pOld)->GetValue();
            m_nActLineWidth = nStartLineWidth;
        }

        if(m_nActLineWidth != nNewLineWidth)
        {
            // Adapt start/end width
            sal_Int32 nValAct = GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit );
            sal_Int32 nValNew = nValAct + (((nNewLineWidth - m_nActLineWidth) * 15) / 10);
            if(nValNew < 0)
                nValNew = 0;
            SetMetricValue( *m_xMtrStartWidth, nValNew, m_ePoolUnit );

            nValAct = GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit );
            nValNew = nValAct + (((nNewLineWidth - m_nActLineWidth) * 15) / 10);
            if(nValNew < 0)
                nValNew = 0;
            SetMetricValue( *m_xMtrEndWidth, nValNew, m_ePoolUnit );
        }

        // Remember current value
        m_nActLineWidth = nNewLineWidth;
    }

    FillXLSet_Impl();
    m_aCtlPreview.Invalidate();

    // Make transparency accessible accordingly
    if( m_xLbLineStyle->get_active() == 0 ) // invisible
    {
        m_xBoxTransparency->set_sensitive(false);
    }
    else
    {
        m_xBoxTransparency->set_sensitive(true);
    }

    const bool bHasLineStyle = m_xLbLineStyle->get_active() !=0;
    const bool bHasLineStart = m_xLbStartStyle->get_active() != 0;

    m_xBoxStart->set_sensitive(bHasLineStart && bHasLineStyle);

    const bool bHasLineEnd = m_xLbEndStyle->get_active() != 0;

    m_xBoxEnd->set_sensitive(bHasLineEnd && bHasLineStyle);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartClickHdl_Impl, weld::Toggleable&, void)
{
    if (m_xCbxSynchronize->get_active())
        m_xTsbCenterEnd->set_state(m_xTsbCenterStart->get_state());
    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartListBoxHdl_Impl, weld::ComboBox&, void)
{
    if (m_xCbxSynchronize->get_active())
        m_xLbEndStyle->set_active(m_xLbStartStyle->get_active());

    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartModifyHdl_Impl, weld::MetricSpinButton&,&nbsp;void)
{
    if (m_xCbxSynchronize->get_active())
        m_xMtrEndWidth->set_value(m_xMtrStartWidth->get_value(FieldUnit::NONE), FieldUnit::NONE);

    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeEdgeStyleHdl_Impl, weld::ComboBox&, void)
{
    ChangePreviewHdl_Impl( nullptr );
}

// fdo#43209
IMPL_LINK_NOARG(SvxLineTabPage, ChangeCapStyleHdl_Impl, weld::ComboBox&, void)
{
    ChangePreviewHdl_Impl( nullptr );
}

IMPL_LINK_NOARG(SvxLineTabPage, ClickInvisibleHdl_Impl, weld::ComboBox&, void)
{
    ClickInvisibleHdl_Impl();
}

void SvxLineTabPage::ClickInvisibleHdl_Impl()
{
    if( m_xLbLineStyle->get_active() == 0 ) // invisible
    {
        if(!m_bSymbols)
            m_xBoxColor->set_sensitive(false);

        m_xBoxWidth->set_sensitive(false);

        if( m_xFlLineEnds->get_sensitive() )
        {
            m_xBoxStart->set_sensitive(false);
            m_xBoxArrowStyles->set_sensitive(false);
            m_xGridEdgeCaps->set_sensitive(false);
        }
    }
    else
    {
        // set cap style associated to the line style
        sal_Int32 nPos = m_xLbLineStyle->get_active();
        if( nPos > 1 && m_pDashList->Count() > static_cast<tools::Long>( nPos - 2 ) )
        {
            css::drawing::DashStyle eStyle =
                m_pDashList->GetDash( nPos - 2 )->GetDash().GetDashStyle();
            if ( eStyle == drawing::DashStyle_RECT || eStyle == drawing::DashStyle_RECTRELATIVE)
                m_xLBCapStyle->set_active(0);
            else
                m_xLBCapStyle->set_active(1);
        }

        m_xBoxColor->set_sensitive(true);
        m_xBoxWidth->set_sensitive(true);

        if (m_xFlLineEnds->get_sensitive())
        {
            m_xBoxArrowStyles->set_sensitive(true);
            m_xGridEdgeCaps->set_sensitive(true);
        }
    }
    ChangePreviewHdl_Impl( nullptr );
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndClickHdl_Impl, weld::Toggleable&, void)
{
    if (m_xCbxSynchronize->get_active())
        m_xTsbCenterStart->set_state(m_xTsbCenterEnd->get_state());

    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndListBoxHdl_Impl, weld::ComboBox&, void)
{
    if (m_xCbxSynchronize->get_active())
        m_xLbStartStyle->set_active(m_xLbEndStyle->get_active());

    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndModifyHdl_Impl, weld::MetricSpinButton&,&nbsp;void)
{
    if (m_xCbxSynchronize->get_active())
        m_xMtrStartWidth->set_value(m_xMtrEndWidth->get_value(FieldUnit::NONE), FieldUnit::NONE);

    ChangePreviewHdl_Impl(nullptr);
}

IMPL_LINK_NOARG(SvxLineTabPage, ChangeTransparentHdl_Impl, weld::MetricSpinButton&,&nbsp;void)
{
    sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT);

    m_rXLSet.Put(XLineTransparenceItem(nVal));

    FillXLSet_Impl();

    m_aCtlPreview.Invalidate();
}

void SvxLineTabPage::FillUserData()
{
    // Write the synched value to the INI file
    OUString aStrUserData = OUString::boolean(m_xCbxSynchronize->get_active());
    SetUserData( aStrUserData );
}

// #58425# Symbols on a list (e.g. StarChart)
void SvxLineTabPage::PopulateMenus()
{
    ScopedVclPtrInstance< VirtualDevice > pVD;

    // Initialize popup
    if (!m_xGalleryMenu)
    {
        m_xGalleryMenu = m_xBuilder->weld_menu(u"gallerysubmenu"_ustr);
        weld::WaitObject aWait(GetFrameWeld());
        // Get gallery entries
        GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, m_aGrfNames);

        sal_uInt32 i = 0;
        for (auto const& grfName : m_aGrfNames)
        {
            const OUString *pUIName = &grfName;

            // Convert URL encodings to UI characters (e.g. %20 for spaces)
            OUString aPhysicalName;
            if (osl::FileBase::getSystemPathFromFileURL(grfName, aPhysicalName)
                == osl::FileBase::E_None)
            {
                pUIName = &aPhysicalName;
            }

            SvxBmpItemInfo* pInfo = new SvxBmpItemInfo;
            pInfo->pBrushItem.reset(new SvxBrushItem(grfName, u""_ustr, GPOS_AREA, SID_ATTR_BRUSH));
            pInfo->sItemId = "gallery" + OUString::number(i);
            m_aGalleryBrushItems.emplace_back(pInfo);
            const Graphic* pGraphic = pInfo->pBrushItem->GetGraphic();

            if(pGraphic)
            {
                BitmapEx aBitmap(pGraphic->GetBitmapEx());
                Size aSize(aBitmap.GetSizePixel());
                if(aSize.Width()  > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT)
                {
                    bool bWidth = aSize.Width() > aSize.Height();
                    double nScale = bWidth ?
                                        double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width()):
                                        double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height());
                    aBitmap.Scale(nScale, nScale);

                }
                pVD->SetOutputSizePixel(aBitmap.GetSizePixel());
                pVD->DrawBitmapEx(Point(), aBitmap);
                m_xGalleryMenu->append(pInfo->sItemId, *pUIName, *pVD);
            }
            else
            {
                m_xGalleryMenu->append(pInfo->sItemId, *pUIName);
            }
            ++i;
        }

        if (m_aGrfNames.empty())
            m_xSymbolMB->set_item_sensitive(u"gallery"_ustr, false);
    }

    if (m_xSymbolsMenu || !m_pSymbolList)
        return;

    m_xSymbolsMenu = m_xBuilder->weld_menu(u"symbolssubmenu"_ustr);
    ScopedVclPtrInstance< VirtualDevice > pVDev;
    pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
    std::unique_ptr<SdrModel> pModel(
        new SdrModel(nullptr, nullptr, true));
    // Page
    rtl::Reference<SdrPage> pPage = new SdrPage( *pModel, false );
    pPage->SetSize(Size(1000,1000));
    pModel->InsertPage( pPage.get(), 0 );
    {
        // 3D View
        SdrView aView( *pModel, pVDev );
        aView.hideMarkHandles();
        aView.ShowSdrPage(pPage.get());

        // Generate invisible square to give all symbols a
        // bitmap size, which is independent from specific glyph
        rtl::Reference<SdrObject> pInvisibleSquare=m_pSymbolList->GetObj(0);

        // directly clone to target SdrModel
        pInvisibleSquare = pInvisibleSquare->CloneSdrObject(*pModel);

        pPage->NbcInsertObject(pInvisibleSquare.get());
        pInvisibleSquare->SetMergedItem(XFillTransparenceItem(100));
        pInvisibleSquare->SetMergedItem(XLineTransparenceItem(100));

        for(size_t i=0; i < m_pSymbolList->GetObjCount(); ++i)
        {
            rtl::Reference<SdrObject> pObj=m_pSymbolList->GetObj(i);
            assert(pObj);

            // directly clone to target SdrModel
            pObj = pObj->CloneSdrObject(*pModel);

            m_aGrfNames.emplace_back("");
            pPage->NbcInsertObject(pObj.get());
            if(m_xSymbolAttr)
            {
                pObj->SetMergedItemSet(*m_xSymbolAttr);
            }
            else
            {
                pObj->SetMergedItemSet(m_rOutAttrs);
            }
            aView.MarkAll();
            BitmapEx aBitmapEx(aView.GetMarkedObjBitmapEx());
            GDIMetaFile aMeta(aView.GetMarkedObjMetaFile());
            aView.UnmarkAll();
            pPage->RemoveObject(1);
            pObj.clear();

            SvxBmpItemInfo* pInfo = new SvxBmpItemInfo;
            pInfo->pBrushItem.reset(new SvxBrushItem(Graphic(aMeta), GPOS_AREA, SID_ATTR_BRUSH));
            pInfo->sItemId = "symbol" + OUString::number(i);
            m_aSymbolBrushItems.emplace_back(pInfo);

            Size aSize(aBitmapEx.GetSizePixel());
            if(aSize.Width() > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT)
            {
                bool bWidth = aSize.Width() > aSize.Height();
                double nScale = bWidth ?
                                    double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width()):
                                    double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height());
                aBitmapEx.Scale(nScale, nScale);
            }
            pVD->SetOutputSizePixel(aBitmapEx.GetSizePixel());
            pVD->DrawBitmapEx(Point(), aBitmapEx);
            m_xSymbolsMenu->append(pInfo->sItemId, u""_ustr, *pVD);
        }
        pPage->RemoveObject(0);
        pInvisibleSquare.clear();

        if (m_aGrfNames.empty())
            m_xSymbolMB->set_item_sensitive(u"symbols"_ustr, false);
    }
}

// #58425# Symbols on a list (e.g. StarChart)
// Handler for menu button
IMPL_LINK(SvxLineTabPage, GraphicHdl_Impl, const OUString&, rIdent, void)
{
    const Graphic* pGraphic = nullptr;
    Graphic aGraphic;
    bool bResetSize = false;
    bool bEnable = true;
    tools::Long nPreviousSymbolType = m_nSymbolType;

    std::u16string_view sNumber;
    if (rIdent.startsWith("gallery", &sNumber))
    {
        SvxBmpItemInfo* pInfo = m_aGalleryBrushItems[o3tl::toUInt32(sNumber)].get();
        pGraphic = pInfo->pBrushItem->GetGraphic();
        m_nSymbolType = SVX_SYMBOLTYPE_BRUSHITEM;
    }
    else if (rIdent.startsWith("symbol", &sNumber))
    {
        m_nSymbolType = o3tl::toUInt32(sNumber);
        SvxBmpItemInfo* pInfo = m_aSymbolBrushItems[m_nSymbolType].get();
        pGraphic = pInfo->pBrushItem->GetGraphic();
    }
    else if (rIdent == "automatic")
    {
        pGraphic=&m_aAutoSymbolGraphic;
        m_aAutoSymbolGraphic.SetPrefSize( Size(253,253) );
        m_nSymbolType=SVX_SYMBOLTYPE_AUTO;
    }
    else if (rIdent == "none")
    {
        m_nSymbolType=SVX_SYMBOLTYPE_NONE;
        pGraphic=nullptr;
        bEnable = false;
    }
    else if (rIdent == "file")
    {
        SvxOpenGraphicDialog aGrfDlg(CuiResId(RID_CUISTR_EDIT_GRAPHIC), GetFrameWeld());
        aGrfDlg.EnableLink(false);
        aGrfDlg.AsLink(false);
        if( !aGrfDlg.Execute() )
        {
            // Remember selected filters
            if( !aGrfDlg.GetGraphic(aGraphic) )
            {
                m_nSymbolType=SVX_SYMBOLTYPE_BRUSHITEM;
                pGraphic = &aGraphic;
                bResetSize = true;
            }
        }
        if( !pGraphic )
            return;
    }

    if (pGraphic)
    {
        Size aSize = SvxNumberFormat::GetGraphicSizeMM100(pGraphic);
        aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(m_ePoolUnit));
        m_aSymbolGraphic=*pGraphic;
        if( bResetSize )
        {
            m_aSymbolSize=aSize;
        }
        else if( nPreviousSymbolType == SVX_SYMBOLTYPE_BRUSHITEM )
        {   //#i31097# Data Point Symbol size changes when a different symbol is chosen(maoyg)
            if( m_aSymbolSize.Width() != m_aSymbolSize.Height() )
            {
                aSize.setWidth( static_cast<tools::Long>( m_aSymbolSize.Width() + m_aSymbolSize.Height() )/2 );
                aSize.setHeight( static_cast<tools::Long>( m_aSymbolSize.Width() + m_aSymbolSize.Height() )/2 );
                m_aSymbolSize = aSize;
            }
        }
        m_aCtlPreview.SetSymbol(&m_aSymbolGraphic,m_aSymbolSize);
    }
    else
    {
        m_aSymbolGraphic=Graphic();
        m_aCtlPreview.SetSymbol(nullptr,m_aSymbolSize);
        bEnable = false;
    }
    m_aSymbolLastSize=m_aSymbolSize;
    SetMetricValue(*m_xSymbolWidthMF,  m_aSymbolSize.Width(), m_ePoolUnit);
    SetMetricValue(*m_xSymbolHeightMF, m_aSymbolSize.Height(), m_ePoolUnit);

    m_xGridIconSize->set_sensitive(bEnable);
    m_aCtlPreview.Invalidate();
}

IMPL_LINK( SvxLineTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void)
{
    m_bNewSize = true;
    bool bWidth = &rField == m_xSymbolWidthMF.get();
    m_bLastWidthModified = bWidth;
    bool bRatio = m_xSymbolRatioCB->get_active();
    tools::Long nWidthVal = static_cast<tools::Long>(m_xSymbolWidthMF->denormalize(m_xSymbolWidthMF->get_value(FieldUnit::MM_100TH)));
    tools::Long nHeightVal= static_cast<tools::Long>(m_xSymbolHeightMF->denormalize(m_xSymbolHeightMF->get_value(FieldUnit::MM_100TH)));
    nWidthVal = OutputDevice::LogicToLogic(nWidthVal,MapUnit::Map100thMM, m_ePoolUnit );
    nHeightVal = OutputDevice::LogicToLogic(nHeightVal,MapUnit::Map100thMM, m_ePoolUnit);
    m_aSymbolSize = Size(nWidthVal,nHeightVal);
    double fSizeRatio = double(1);

    if(bRatio)
    {
        if (m_aSymbolLastSize.Height() && m_aSymbolLastSize.Width())
            fSizeRatio = static_cast<double>(m_aSymbolLastSize.Width()) / m_aSymbolLastSize.Height();
    }

    if (bWidth)
    {
        tools::Long nDelta = nWidthVal - m_aSymbolLastSize.Width();
        m_aSymbolSize.setWidth( nWidthVal );
        if (bRatio)
        {
            m_aSymbolSize.setHeight( m_aSymbolLastSize.Height() + static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio) );
            m_aSymbolSize.setHeight( OutputDevice::LogicToLogic( m_aSymbolSize.Height(), m_ePoolUnit, MapUnit::Map100thMM ) );
//TODO            m_xSymbolHeightMF->SetUserValue(m_xSymbolHeightMF->normalize(m_aSymbolSize.Height()), FieldUnit::MM_100TH);
            m_xSymbolHeightMF->set_value(m_xSymbolHeightMF->normalize(m_aSymbolSize.Height()), FieldUnit::MM_100TH);
        }
    }
    else
    {
        tools::Long nDelta = nHeightVal - m_aSymbolLastSize.Height();
        m_aSymbolSize.setHeight( nHeightVal );
        if (bRatio)
        {
            m_aSymbolSize.setWidth( m_aSymbolLastSize.Width() + static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio) );
            m_aSymbolSize.setWidth( OutputDevice::LogicToLogic( m_aSymbolSize.Width(), m_ePoolUnit, MapUnit::Map100thMM ) );
//TODO            m_xSymbolWidthMF->SetUserValue(m_xSymbolWidthMF->normalize(m_aSymbolSize.Width()), FieldUnit::MM_100TH);
            m_xSymbolWidthMF->set_value(m_xSymbolWidthMF->normalize(m_aSymbolSize.Width()), FieldUnit::MM_100TH);
        }
    }
    m_aCtlPreview.ResizeSymbol(m_aSymbolSize);
    m_aSymbolLastSize=m_aSymbolSize;
}

IMPL_LINK(SvxLineTabPage, RatioHdl_Impl, weld::Toggleable&, rBox, void)
{
    if (rBox.get_active())
    {
        if (m_bLastWidthModified)
            SizeHdl_Impl(*m_xSymbolWidthMF);
        else
            SizeHdl_Impl(*m_xSymbolHeightMF);
    }
}

void SvxLineTabPage::PageCreated(const SfxAllItemSet& aSet)
{
    const SvxDashListItem* pDashListItem = aSet.GetItem<SvxDashListItem>(SID_DASH_LIST, false);
    const SvxLineEndListItem* pLineEndListItem = aSet.GetItem<SvxLineEndListItem>(SID_LINEEND_LIST, false);
    const SfxUInt16Item* pPageTypeItem = aSet.GetItem<SfxUInt16Item>(SID_PAGE_TYPE, false);
    const SfxUInt16Item* pDlgTypeItem = aSet.GetItem<SfxUInt16Item>(SID_DLG_TYPE, false);
    const OfaPtrItem* pSdrObjListItem = aSet.GetItem<OfaPtrItem>(SID_OBJECT_LIST, false);
    const SfxTabDialogItem* pSymbolAttrItem = aSet.GetItem<SfxTabDialogItem>(SID_ATTR_SET, false);
    const SvxGraphicItem* pGraphicItem = aSet.GetItem<SvxGraphicItem>(SID_GRAPHIC, false);

    if (pDashListItem)
        SetDashList(pDashListItem->GetDashList());
    if (pLineEndListItem)
        SetLineEndList(pLineEndListItem->GetLineEndList());
    if (pPageTypeItem)
        SetPageType(static_cast<PageType>(pPageTypeItem->GetValue()));
    if (pDlgTypeItem)
        SetDlgType(pDlgTypeItem->GetValue());

    if(pSdrObjListItem) //symbols
    {
        ShowSymbolControls(true);
        m_pSymbolList = static_cast<SdrObjList*>(pSdrObjListItem->GetValue());
        if (pSymbolAttrItem)
            m_xSymbolAttr.reset(new SfxItemSet(pSymbolAttrItem->GetItemSet()));
        if(pGraphicItem)
            m_aAutoSymbolGraphic = pGraphicItem->GetGraphic();
    }

    Construct();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=93 H=98 G=95

¤ Dauer der Verarbeitung: 0.17 Sekunden  ¤

*© 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.