summaryrefslogtreecommitdiff
path: root/svtools
diff options
context:
space:
mode:
Diffstat (limited to 'svtools')
-rw-r--r--svtools/source/control/valueacc.cxx983
-rw-r--r--svtools/source/control/valueimp.hxx198
-rw-r--r--svtools/source/control/valueset.cxx1455
3 files changed, 2636 insertions, 0 deletions
diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx
index 443dfc875d70..34cf5c41a0aa 100644
--- a/svtools/source/control/valueacc.cxx
+++ b/svtools/source/control/valueacc.cxx
@@ -61,6 +61,32 @@ uno::Reference< accessibility::XAccessible > const & ValueSetItem::GetAccessible
return mxAcc;
}
+SvtValueSetItem::SvtValueSetItem( SvtValueSet& rParent )
+ : mrParent(rParent)
+ , mnId(0)
+ , meType(VALUESETITEM_NONE)
+ , mbVisible(true)
+ , mpData(nullptr)
+ , mxAcc()
+{
+}
+
+
+SvtValueSetItem::~SvtValueSetItem()
+{
+ if( mxAcc.is() )
+ {
+ static_cast< ValueItemAcc* >( mxAcc.get() )->ParentDestroyed();
+ }
+}
+
+uno::Reference< accessibility::XAccessible > const & SvtValueSetItem::GetAccessible( bool bIsTransientChildrenDisabled )
+{
+ if( !mxAcc.is() )
+ mxAcc = new SvtValueItemAcc( this, bIsTransientChildrenDisabled );
+
+ return mxAcc;
+}
ValueSetAcc::ValueSetAcc( ValueSet* pParent ) :
ValueSetAccComponentBase (m_aMutex),
@@ -1036,4 +1062,961 @@ sal_Int64 SAL_CALL ValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >&
return nRet;
}
+SvtValueItemAcc::SvtValueItemAcc( SvtValueSetItem* pParent, bool bIsTransientChildrenDisabled ) :
+ mpParent( pParent ),
+ mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled )
+{
+}
+
+SvtValueItemAcc::~SvtValueItemAcc()
+{
+}
+
+void SvtValueItemAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
+{
+ if( !nEventId )
+ return;
+
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners );
+ accessibility::AccessibleEventObject aEvtObject;
+
+ aEvtObject.EventId = nEventId;
+ aEvtObject.Source = static_cast<uno::XWeak*>(this);
+ aEvtObject.NewValue = rNewValue;
+ aEvtObject.OldValue = rOldValue;
+
+ for (auto const& tmpListener : aTmpListeners)
+ {
+ tmpListener->notifyEvent( aEvtObject );
+ }
+}
+
+
+void SvtValueItemAcc::ParentDestroyed()
+{
+ const ::osl::MutexGuard aGuard( maMutex );
+ mpParent = nullptr;
+}
+
+namespace
+{
+ class theSvtValueItemAccUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSvtValueItemAccUnoTunnelId > {};
+}
+
+const uno::Sequence< sal_Int8 >& SvtValueItemAcc::getUnoTunnelId()
+{
+ return theSvtValueItemAccUnoTunnelId::get().getSeq();
+}
+
+
+SvtValueItemAcc* SvtValueItemAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
+ throw()
+{
+ try
+ {
+ uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
+ return( xUnoTunnel.is() ? reinterpret_cast<SvtValueItemAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( SvtValueItemAcc::getUnoTunnelId() ))) : nullptr );
+ }
+ catch(const css::uno::Exception&)
+ {
+ return nullptr;
+ }
+}
+
+
+uno::Reference< accessibility::XAccessibleContext > SAL_CALL SvtValueItemAcc::getAccessibleContext()
+{
+ return this;
+}
+
+
+sal_Int32 SAL_CALL SvtValueItemAcc::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueItemAcc::getAccessibleChild( sal_Int32 )
+{
+ throw lang::IndexOutOfBoundsException();
+}
+
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueItemAcc::getAccessibleParent()
+{
+ const SolarMutexGuard aSolarGuard;
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ if( mpParent )
+ xRet = mpParent->mrParent.mxAccessible;
+
+ return xRet;
+}
+
+
+sal_Int32 SAL_CALL SvtValueItemAcc::getAccessibleIndexInParent()
+{
+ const SolarMutexGuard aSolarGuard;
+ // The index defaults to -1 to indicate the child does not belong to its
+ // parent.
+ sal_Int32 nIndexInParent = -1;
+
+ if( mpParent )
+ {
+ bool bDone = false;
+
+ sal_uInt16 nCount = mpParent->mrParent.ImplGetVisibleItemCount();
+ SvtValueSetItem* pItem;
+ for (sal_uInt16 i=0; i<nCount && !bDone; i++)
+ {
+ // Guard the retrieval of the i-th child with a try/catch block
+ // just in case the number of children changes in the mean time.
+ try
+ {
+ pItem = mpParent->mrParent.ImplGetItem(i);
+ }
+ catch (const lang::IndexOutOfBoundsException&)
+ {
+ pItem = nullptr;
+ }
+
+ // Do not create an accessible object for the test.
+ if (pItem != nullptr && pItem->mxAcc.is())
+ if (pItem->GetAccessible( mbIsTransientChildrenDisabled ).get() == this )
+ {
+ nIndexInParent = i;
+ bDone = true;
+ }
+ }
+ }
+
+ //if this valueset contain a none field(common value is default), then we should increase the real index and set the noitem index value equal 0.
+ if ( mpParent && ( (mpParent->mrParent.GetStyle() & WB_NONEFIELD) != 0 ) )
+ {
+ SvtValueSetItem* pFirstItem = mpParent->mrParent.ImplGetItem (VALUESET_ITEM_NONEITEM);
+ if( pFirstItem && pFirstItem ->GetAccessible(mbIsTransientChildrenDisabled).get() == this )
+ nIndexInParent = 0;
+ else
+ nIndexInParent++;
+ }
+ return nIndexInParent;
+}
+
+
+sal_Int16 SAL_CALL SvtValueItemAcc::getAccessibleRole()
+{
+ return accessibility::AccessibleRole::LIST_ITEM;
+}
+
+
+OUString SAL_CALL SvtValueItemAcc::getAccessibleDescription()
+{
+ return OUString();
+}
+
+
+OUString SAL_CALL SvtValueItemAcc::getAccessibleName()
+{
+ const SolarMutexGuard aSolarGuard;
+
+ if( mpParent )
+ {
+ if (mpParent->maText.isEmpty())
+ return "Item " + OUString::number(static_cast<sal_Int32>(mpParent->mnId));
+ else
+ return mpParent->maText;
+ }
+
+ return OUString();
+}
+
+
+uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL SvtValueItemAcc::getAccessibleRelationSet()
+{
+ return uno::Reference< accessibility::XAccessibleRelationSet >();
+}
+
+
+uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL SvtValueItemAcc::getAccessibleStateSet()
+{
+ const SolarMutexGuard aSolarGuard;
+ ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper;
+
+ if( mpParent )
+ {
+ pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
+ pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
+ pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
+ pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
+ if ( !mbIsTransientChildrenDisabled )
+ pStateSet->AddState (accessibility::AccessibleStateType::TRANSIENT);
+
+ // SELECTABLE
+ pStateSet->AddState( accessibility::AccessibleStateType::SELECTABLE );
+ // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSABLE );
+
+ // SELECTED
+ if( mpParent->mrParent.GetSelectedItemId() == mpParent->mnId )
+ {
+ pStateSet->AddState( accessibility::AccessibleStateType::SELECTED );
+ // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSED );
+ }
+ }
+
+ return pStateSet;
+}
+
+
+lang::Locale SAL_CALL SvtValueItemAcc::getLocale()
+{
+ const SolarMutexGuard aSolarGuard;
+ uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() );
+ lang::Locale aRet( "", "", "" );
+
+ if( xParent.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+
+ if( xParentContext.is() )
+ aRet = xParentContext->getLocale();
+ }
+
+ return aRet;
+}
+
+
+void SAL_CALL SvtValueItemAcc::addAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+{
+ const ::osl::MutexGuard aGuard( maMutex );
+
+ if( !rxListener.is() )
+ return;
+
+ bool bFound = false;
+
+ for (auto const& eventListener : mxEventListeners)
+ {
+ if(eventListener == rxListener)
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ mxEventListeners.push_back( rxListener );
+}
+
+
+void SAL_CALL SvtValueItemAcc::removeAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+{
+ const ::osl::MutexGuard aGuard( maMutex );
+
+ if( rxListener.is() )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter =
+ std::find(mxEventListeners.begin(), mxEventListeners.end(), rxListener);
+
+ if (aIter != mxEventListeners.end())
+ mxEventListeners.erase(aIter);
+ }
+}
+
+
+sal_Bool SAL_CALL SvtValueItemAcc::containsPoint( const awt::Point& aPoint )
+{
+ const awt::Rectangle aRect( getBounds() );
+ const Point aSize( aRect.Width, aRect.Height );
+ const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
+
+ return tools::Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
+}
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueItemAcc::getAccessibleAtPoint( const awt::Point& )
+{
+ uno::Reference< accessibility::XAccessible > xRet;
+ return xRet;
+}
+
+awt::Rectangle SAL_CALL SvtValueItemAcc::getBounds()
+{
+ const SolarMutexGuard aSolarGuard;
+ awt::Rectangle aRet;
+
+ if( mpParent )
+ {
+ tools::Rectangle aRect( mpParent->mrParent.GetItemRect(mpParent->mnId) );
+ tools::Rectangle aParentRect( Point(), mpParent->mrParent.GetOutputSizePixel() );
+
+ aRect.Intersection( aParentRect );
+
+ aRet.X = aRect.Left();
+ aRet.Y = aRect.Top();
+ aRet.Width = aRect.GetWidth();
+ aRet.Height = aRect.GetHeight();
+ }
+
+ return aRet;
+}
+
+awt::Point SAL_CALL SvtValueItemAcc::getLocation()
+{
+ const awt::Rectangle aRect( getBounds() );
+ awt::Point aRet;
+
+ aRet.X = aRect.X;
+ aRet.Y = aRect.Y;
+
+ return aRet;
+}
+
+awt::Point SAL_CALL SvtValueItemAcc::getLocationOnScreen()
+{
+ const SolarMutexGuard aSolarGuard;
+ uno::Reference<accessibility::XAccessible> xParent(getAccessibleParent());
+ awt::Point aRet;
+
+ if (mpParent && xParent)
+ {
+ uno::Reference<accessibility::XAccessibleContext> xParentContext(xParent->getAccessibleContext());
+ uno::Reference<accessibility::XAccessibleComponent> xParentComponent(xParentContext, css::uno::UNO_QUERY_THROW);
+ awt::Point aParentScreenLoc(xParentComponent->getLocationOnScreen());
+ const Point aOwnRelativeLoc = mpParent->mrParent.GetItemRect(mpParent->mnId).TopLeft();
+
+ aRet.X = aParentScreenLoc.X + aOwnRelativeLoc.X();
+ aRet.X = aParentScreenLoc.Y + aOwnRelativeLoc.Y();
+ }
+
+ return aRet;
+}
+
+awt::Size SAL_CALL SvtValueItemAcc::getSize()
+{
+ const awt::Rectangle aRect( getBounds() );
+ awt::Size aRet;
+
+ aRet.Width = aRect.Width;
+ aRet.Height = aRect.Height;
+
+ return aRet;
+}
+
+void SAL_CALL SvtValueItemAcc::grabFocus()
+{
+ // nothing to do
+}
+
+sal_Int32 SAL_CALL SvtValueItemAcc::getForeground( )
+{
+ Color nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+sal_Int32 SAL_CALL SvtValueItemAcc::getBackground( )
+{
+ Color nColor;
+ if (mpParent && mpParent->meType == VALUESETITEM_COLOR)
+ nColor = mpParent->maColor;
+ else
+ nColor = Application::GetSettings().GetStyleSettings().GetWindowColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+sal_Int64 SAL_CALL SvtValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >& rId )
+{
+ sal_Int64 nRet;
+
+ if( ( rId.getLength() == 16 ) && ( 0 == memcmp( SvtValueItemAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
+ nRet = reinterpret_cast< sal_Int64 >( this );
+ else
+ nRet = 0;
+
+ return nRet;
+}
+
+SvtValueSetAcc::SvtValueSetAcc( SvtValueSet* pParent ) :
+ ValueSetAccComponentBase (m_aMutex),
+ mpParent( pParent ),
+ mbIsFocused(false)
+{
+}
+
+
+SvtValueSetAcc::~SvtValueSetAcc()
+{
+}
+
+
+void SvtValueSetAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
+{
+ if( !nEventId )
+ return;
+
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners );
+ accessibility::AccessibleEventObject aEvtObject;
+
+ aEvtObject.EventId = nEventId;
+ aEvtObject.Source = static_cast<uno::XWeak*>(this);
+ aEvtObject.NewValue = rNewValue;
+ aEvtObject.OldValue = rOldValue;
+
+ for (auto const& tmpListener : aTmpListeners)
+ {
+ try
+ {
+ tmpListener->notifyEvent( aEvtObject );
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+}
+
+namespace
+{
+ class theSvtValueSetAccUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSvtValueSetAccUnoTunnelId > {};
+}
+
+const uno::Sequence< sal_Int8 >& SvtValueSetAcc::getUnoTunnelId()
+{
+ return theSvtValueSetAccUnoTunnelId::get().getSeq();
+}
+
+
+SvtValueSetAcc* SvtValueSetAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
+ throw()
+{
+ try
+ {
+ uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
+ return( xUnoTunnel.is() ? reinterpret_cast<SvtValueSetAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( SvtValueSetAcc::getUnoTunnelId() ))) : nullptr );
+ }
+ catch(const css::uno::Exception&)
+ {
+ return nullptr;
+ }
+}
+
+
+void SvtValueSetAcc::GetFocus()
+{
+ mbIsFocused = true;
+
+ // Broadcast the state change.
+ css::uno::Any aOldState, aNewState;
+ aNewState <<= css::accessibility::AccessibleStateType::FOCUSED;
+ FireAccessibleEvent(
+ css::accessibility::AccessibleEventId::STATE_CHANGED,
+ aOldState, aNewState);
+}
+
+
+void SvtValueSetAcc::LoseFocus()
+{
+ mbIsFocused = false;
+
+ // Broadcast the state change.
+ css::uno::Any aOldState, aNewState;
+ aOldState <<= css::accessibility::AccessibleStateType::FOCUSED;
+ FireAccessibleEvent(
+ css::accessibility::AccessibleEventId::STATE_CHANGED,
+ aOldState, aNewState);
+}
+
+
+uno::Reference< accessibility::XAccessibleContext > SAL_CALL SvtValueSetAcc::getAccessibleContext()
+{
+ ThrowIfDisposed();
+ return this;
+}
+
+
+sal_Int32 SAL_CALL SvtValueSetAcc::getAccessibleChildCount()
+{
+ const SolarMutexGuard aSolarGuard;
+ ThrowIfDisposed();
+
+ sal_Int32 nCount = mpParent->ImplGetVisibleItemCount();
+ if (HasNoneField())
+ nCount += 1;
+ return nCount;
+}
+
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getAccessibleChild( sal_Int32 i )
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ SvtValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(i));
+
+ if( !pItem )
+ throw lang::IndexOutOfBoundsException();
+
+ uno::Reference< accessibility::XAccessible > xRet = pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ );
+ return xRet;
+}
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getAccessibleParent()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ return mpParent->GetDrawingArea()->get_accessible_parent();
+}
+
+sal_Int32 SAL_CALL SvtValueSetAcc::getAccessibleIndexInParent()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+
+ // -1 for child not found/no parent (according to specification)
+ sal_Int32 nRet = -1;
+
+ uno::Reference<accessibility::XAccessible> xParent(getAccessibleParent());
+ if (!xParent)
+ return nRet;
+
+ try
+ {
+ uno::Reference<accessibility::XAccessibleContext> xParentContext(xParent->getAccessibleContext());
+
+ // iterate over parent's children and search for this object
+ if ( xParentContext.is() )
+ {
+ sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
+ for ( sal_Int32 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild )
+ {
+ uno::Reference<XAccessible> xChild(xParentContext->getAccessibleChild(nChild));
+ if ( xChild.get() == this )
+ nRet = nChild;
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ OSL_FAIL( "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" );
+ }
+
+ return nRet;
+}
+
+sal_Int16 SAL_CALL SvtValueSetAcc::getAccessibleRole()
+{
+ ThrowIfDisposed();
+ return accessibility::AccessibleRole::LIST;
+}
+
+
+OUString SAL_CALL SvtValueSetAcc::getAccessibleDescription()
+{
+ ThrowIfDisposed();
+ return OUString( "ValueSet" );
+}
+
+
+OUString SAL_CALL SvtValueSetAcc::getAccessibleName()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ OUString aRet;
+
+ if (mpParent)
+ {
+ aRet = mpParent->GetAccessibleName();
+ }
+
+ return aRet;
+}
+
+uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL SvtValueSetAcc::getAccessibleRelationSet()
+{
+ ThrowIfDisposed();
+ SolarMutexGuard g;
+ return mpParent->GetDrawingArea()->get_accessible_relation_set();
+}
+
+uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL SvtValueSetAcc::getAccessibleStateSet()
+{
+ ThrowIfDisposed();
+ ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
+
+ // Set some states.
+ pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
+ pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
+ pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
+ pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
+ pStateSet->AddState (accessibility::AccessibleStateType::MANAGES_DESCENDANTS);
+ pStateSet->AddState (accessibility::AccessibleStateType::FOCUSABLE);
+ if (mbIsFocused)
+ pStateSet->AddState (accessibility::AccessibleStateType::FOCUSED);
+
+ return pStateSet;
+}
+
+
+lang::Locale SAL_CALL SvtValueSetAcc::getLocale()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() );
+ lang::Locale aRet( "", "", "" );
+
+ if( xParent.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+
+ if( xParentContext.is() )
+ aRet = xParentContext->getLocale ();
+ }
+
+ return aRet;
+}
+
+
+void SAL_CALL SvtValueSetAcc::addAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (m_aMutex);
+
+ if( !rxListener.is() )
+ return;
+
+ bool bFound = false;
+
+ for (auto const& eventListener : mxEventListeners)
+ {
+ if(eventListener == rxListener)
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ mxEventListeners.push_back( rxListener );
+}
+
+
+void SAL_CALL SvtValueSetAcc::removeAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (m_aMutex);
+
+ if( rxListener.is() )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter =
+ std::find(mxEventListeners.begin(), mxEventListeners.end(), rxListener);
+
+ if (aIter != mxEventListeners.end())
+ mxEventListeners.erase(aIter);
+ }
+}
+
+
+sal_Bool SAL_CALL SvtValueSetAcc::containsPoint( const awt::Point& aPoint )
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ const Point aSize( aRect.Width, aRect.Height );
+ const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
+
+ return tools::Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
+}
+
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getAccessibleAtPoint( const awt::Point& aPoint )
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ const sal_uInt16 nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) );
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ if ( nItemId )
+ {
+ const size_t nItemPos = mpParent->GetItemPos( nItemId );
+
+ if( VALUESET_ITEM_NONEITEM != nItemPos )
+ {
+ SvtValueSetItem *const pItem = mpParent->mItemList[nItemPos];
+ xRet = pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ );
+ }
+ }
+
+ return xRet;
+}
+
+
+awt::Rectangle SAL_CALL SvtValueSetAcc::getBounds()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ const Point aOutPos;
+ const Size aOutSize( mpParent->GetOutputSizePixel() );
+ awt::Rectangle aRet;
+
+ aRet.X = aOutPos.X();
+ aRet.Y = aOutPos.Y();
+ aRet.Width = aOutSize.Width();
+ aRet.Height = aOutSize.Height();
+
+ return aRet;
+}
+
+
+awt::Point SAL_CALL SvtValueSetAcc::getLocation()
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ awt::Point aRet;
+
+ aRet.X = aRect.X;
+ aRet.Y = aRect.Y;
+
+ return aRet;
+}
+
+
+awt::Point SAL_CALL SvtValueSetAcc::getLocationOnScreen()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ awt::Point aScreenLoc(0, 0);
+
+ uno::Reference<accessibility::XAccessible> xParent(getAccessibleParent());
+ if (xParent)
+ {
+ uno::Reference<accessibility::XAccessibleContext> xParentContext(xParent->getAccessibleContext());
+ uno::Reference<accessibility::XAccessibleComponent> xParentComponent(xParentContext, css::uno::UNO_QUERY);
+ OSL_ENSURE( xParentComponent.is(), "SvtValueSetAcc::getLocationOnScreen: no parent component!" );
+ if ( xParentComponent.is() )
+ {
+ awt::Point aParentScreenLoc( xParentComponent->getLocationOnScreen() );
+ awt::Point aOwnRelativeLoc( getLocation() );
+ aScreenLoc.X = aParentScreenLoc.X + aOwnRelativeLoc.X;
+ aScreenLoc.Y = aParentScreenLoc.Y + aOwnRelativeLoc.Y;
+ }
+ }
+
+ return aScreenLoc;
+}
+
+
+awt::Size SAL_CALL SvtValueSetAcc::getSize()
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ awt::Size aRet;
+
+ aRet.Width = aRect.Width;
+ aRet.Height = aRect.Height;
+
+ return aRet;
+}
+
+void SAL_CALL SvtValueSetAcc::grabFocus()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ mpParent->GrabFocus();
+}
+
+sal_Int32 SAL_CALL SvtValueSetAcc::getForeground( )
+{
+ ThrowIfDisposed();
+ Color nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+sal_Int32 SAL_CALL SvtValueSetAcc::getBackground( )
+{
+ ThrowIfDisposed();
+ Color nColor = Application::GetSettings().GetStyleSettings().GetWindowColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+void SAL_CALL SvtValueSetAcc::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ SvtValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
+
+ if(pItem == nullptr)
+ throw lang::IndexOutOfBoundsException();
+
+ mpParent->SelectItem( pItem->mnId );
+ mpParent->Select ();
+}
+
+
+sal_Bool SAL_CALL SvtValueSetAcc::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ SvtValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
+
+ if (pItem == nullptr)
+ throw lang::IndexOutOfBoundsException();
+
+ bool bRet = mpParent->IsItemSelected( pItem->mnId );
+ return bRet;
+}
+
+
+void SAL_CALL SvtValueSetAcc::clearAccessibleSelection()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ mpParent->SetNoSelection();
+}
+
+
+void SAL_CALL SvtValueSetAcc::selectAllAccessibleChildren()
+{
+ ThrowIfDisposed();
+ // unsupported due to single selection only
+}
+
+
+sal_Int32 SAL_CALL SvtValueSetAcc::getSelectedAccessibleChildCount()
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ sal_Int32 nRet = 0;
+
+ for( sal_uInt16 i = 0, nCount = getItemCount(); i < nCount; i++ )
+ {
+ SvtValueSetItem* pItem = getItem (i);
+
+ if( pItem && mpParent->IsItemSelected( pItem->mnId ) )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+
+uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ for( sal_uInt16 i = 0, nCount = getItemCount(), nSel = 0; ( i < nCount ) && !xRet.is(); i++ )
+ {
+ SvtValueSetItem* pItem = getItem(i);
+
+ if( pItem && mpParent->IsItemSelected( pItem->mnId ) && ( nSelectedChildIndex == static_cast< sal_Int32 >( nSel++ ) ) )
+ xRet = pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ );
+ }
+
+ return xRet;
+}
+
+
+void SAL_CALL SvtValueSetAcc::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ ThrowIfDisposed();
+ const SolarMutexGuard aSolarGuard;
+ // Because of the single selection we can reset the whole selection when
+ // the specified child is currently selected.
+ if (isAccessibleChildSelected(nChildIndex))
+ mpParent->SetNoSelection();
+}
+
+
+sal_Int64 SAL_CALL SvtValueSetAcc::getSomething( const uno::Sequence< sal_Int8 >& rId )
+{
+ sal_Int64 nRet;
+
+ if( ( rId.getLength() == 16 ) && ( 0 == memcmp( SvtValueSetAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
+ nRet = reinterpret_cast< sal_Int64 >( this );
+ else
+ nRet = 0;
+
+ return nRet;
+}
+
+
+void SAL_CALL SvtValueSetAcc::disposing()
+{
+ ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy;
+
+ {
+ // Make a copy of the list and clear the original.
+ const SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard (m_aMutex);
+ aListenerListCopy = mxEventListeners;
+ mxEventListeners.clear();
+
+ // Reset the pointer to the parent. It has to be the one who has
+ // disposed us because he is dying.
+ mpParent = nullptr;
+ }
+
+ // Inform all listeners that this objects is disposing.
+ lang::EventObject aEvent (static_cast<accessibility::XAccessible*>(this));
+ for (auto const& listenerCopy : aListenerListCopy)
+ {
+ try
+ {
+ listenerCopy->disposing (aEvent);
+ }
+ catch(const uno::Exception&)
+ {
+ // Ignore exceptions.
+ }
+ }
+}
+
+
+sal_uInt16 SvtValueSetAcc::getItemCount() const
+{
+ sal_uInt16 nCount = mpParent->ImplGetVisibleItemCount();
+ // When the None-Item is visible then increase the number of items by
+ // one.
+ if (HasNoneField())
+ nCount += 1;
+ return nCount;
+}
+
+SvtValueSetItem* SvtValueSetAcc::getItem (sal_uInt16 nIndex) const
+{
+ SvtValueSetItem* pItem = nullptr;
+
+ if (HasNoneField())
+ {
+ if (nIndex == 0)
+ // When present the first item is the then always visible none field.
+ pItem = mpParent->ImplGetItem (VALUESET_ITEM_NONEITEM);
+ else
+ // Shift down the index to compensate for the none field.
+ nIndex -= 1;
+ }
+ if (pItem == nullptr)
+ pItem = mpParent->ImplGetItem (nIndex);
+
+ return pItem;
+}
+
+
+void SvtValueSetAcc::ThrowIfDisposed()
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ SAL_WARN("svx", "Calling disposed object. Throwing exception:");
+ throw lang::DisposedException (
+ "object has been already disposed",
+ static_cast<uno::XWeak*>(this));
+ }
+ else
+ {
+ DBG_ASSERT (mpParent!=nullptr, "SvtValueSetAcc not disposed but mpParent == NULL");
+ }
+}
+
+bool SvtValueSetAcc::HasNoneField() const
+{
+ assert(mpParent && "SvtValueSetAcc::HasNoneField called with mpParent==NULL");
+ return ((mpParent->GetStyle() & WB_NONEFIELD) != 0);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx
index b791b4243672..66c59fa6f24b 100644
--- a/svtools/source/control/valueimp.hxx
+++ b/svtools/source/control/valueimp.hxx
@@ -48,6 +48,7 @@ enum ValueSetItemType
};
class ValueSet;
+class SvtValueSet;
struct ValueSetItem
{
@@ -68,6 +69,25 @@ struct ValueSetItem
GetAccessible( bool bIsTransientChildrenDisabled );
};
+struct SvtValueSetItem
+{
+ SvtValueSet& mrParent;
+ sal_uInt16 mnId;
+ sal_uInt8 meType;
+ bool mbVisible;
+ Image maImage;
+ Color maColor;
+ OUString maText;
+ void* mpData;
+ css::uno::Reference< css::accessibility::XAccessible > mxAcc;
+
+ explicit SvtValueSetItem( SvtValueSet& rParent );
+ ~SvtValueSetItem();
+
+ css::uno::Reference< css::accessibility::XAccessible > const &
+ GetAccessible( bool bIsTransientChildrenDisabled );
+};
+
typedef ::cppu::WeakComponentImplHelper<
css::accessibility::XAccessible,
css::accessibility::XAccessibleEventBroadcaster,
@@ -191,6 +211,121 @@ private:
bool HasNoneField() const;
};
+class SvtValueSetAcc :
+ public ::cppu::BaseMutex,
+ public ValueSetAccComponentBase
+{
+public:
+
+ explicit SvtValueSetAcc(SvtValueSet* pParent);
+ virtual ~SvtValueSetAcc() override;
+
+ void FireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue );
+ bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
+
+ static SvtValueSetAcc* getImplementation( const css::uno::Reference< css::uno::XInterface >& rxData ) throw();
+
+public:
+
+ /** Called by the corresponding ValueSet when it gets the focus.
+ Stores the new focus state and broadcasts a state change event.
+ */
+ void GetFocus();
+
+ /** Called by the corresponding ValueSet when it loses the focus.
+ Stores the new focus state and broadcasts a state change event.
+ */
+ void LoseFocus();
+
+ // XAccessible
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override;
+
+ // XAccessibleEventBroadcaster
+ virtual void SAL_CALL addAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
+ virtual void SAL_CALL removeAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) override;
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) override;
+ virtual OUString SAL_CALL getAccessibleDescription( ) override;
+ virtual OUString SAL_CALL getAccessibleName( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) override;
+ virtual css::lang::Locale SAL_CALL getLocale( ) override;
+
+ // XAccessibleComponent
+ virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ virtual css::awt::Rectangle SAL_CALL getBounds( ) override;
+ virtual css::awt::Point SAL_CALL getLocation( ) override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen( ) override;
+ virtual css::awt::Size SAL_CALL getSize( ) override;
+ virtual void SAL_CALL grabFocus( ) override;
+ virtual sal_Int32 SAL_CALL getForeground( ) override;
+ virtual sal_Int32 SAL_CALL getBackground( ) override;
+
+ // XAccessibleSelection
+ virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) override;
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) override;
+ virtual void SAL_CALL clearAccessibleSelection( ) override;
+ virtual void SAL_CALL selectAllAccessibleChildren( ) override;
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) override;
+ virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) override;
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override;
+
+private:
+ ::std::vector< css::uno::Reference<
+ css::accessibility::XAccessibleEventListener > > mxEventListeners;
+ SvtValueSet* mpParent;
+ /// The current FOCUSED state.
+ bool mbIsFocused;
+
+ static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId();
+
+ /** Tell all listeners that the object is dying. This callback is
+ usually called from the WeakComponentImplHelper class.
+ */
+ virtual void SAL_CALL disposing() override;
+
+ /** Return the number of items. This takes the None-Item into account.
+ */
+ sal_uInt16 getItemCount() const;
+
+ /** Return the item associated with the given index. The None-Item is
+ taken into account which, when present, is taken to be the first
+ (with index 0) item.
+ @param nIndex
+ Index of the item to return. The index 0 denotes the None-Item
+ when present.
+ @return
+ Returns NULL when the given index is out of range.
+ */
+ SvtValueSetItem* getItem (sal_uInt16 nIndex) const;
+
+ /** Check whether or not the object has been disposed (or is in the
+ state of being disposed). If that is the case then
+ DisposedException is thrown to inform the (indirect) caller of the
+ foul deed.
+ @throws css::lang::DisposedException
+ */
+ void ThrowIfDisposed();
+
+ /** Check whether the value set has a 'none' field, i.e. a field (button)
+ that deselects any items (selects none of them).
+ @return
+ Returns <true/> if there is a 'none' field and <false/> if it is
+ missing.
+ */
+ bool HasNoneField() const;
+};
+
+
class ValueItemAcc : public ::cppu::WeakImplHelper< css::accessibility::XAccessible,
css::accessibility::XAccessibleEventBroadcaster,
css::accessibility::XAccessibleContext,
@@ -254,6 +389,69 @@ public:
virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override;
};
+class SvtValueItemAcc : public ::cppu::WeakImplHelper< css::accessibility::XAccessible,
+ css::accessibility::XAccessibleEventBroadcaster,
+ css::accessibility::XAccessibleContext,
+ css::accessibility::XAccessibleComponent,
+ css::lang::XUnoTunnel >
+{
+private:
+
+ ::std::vector< css::uno::Reference<
+ css::accessibility::XAccessibleEventListener > > mxEventListeners;
+ ::osl::Mutex maMutex;
+ SvtValueSetItem* mpParent;
+ bool mbIsTransientChildrenDisabled;
+
+ static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId();
+
+public:
+
+ SvtValueItemAcc(SvtValueSetItem* pParent, bool bIsTransientChildrenDisabled);
+ virtual ~SvtValueItemAcc() override;
+
+ void ParentDestroyed();
+
+ void FireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue );
+
+ static SvtValueItemAcc* getImplementation( const css::uno::Reference< css::uno::XInterface >& rxData ) throw();
+
+public:
+
+ // XAccessible
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override;
+
+ // XAccessibleEventBroadcaster
+ virtual void SAL_CALL addAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
+ virtual void SAL_CALL removeAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) override;
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) override;
+ virtual OUString SAL_CALL getAccessibleDescription( ) override;
+ virtual OUString SAL_CALL getAccessibleName( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) override;
+ virtual css::lang::Locale SAL_CALL getLocale( ) override;
+
+ // XAccessibleComponent
+ virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ virtual css::awt::Rectangle SAL_CALL getBounds( ) override;
+ virtual css::awt::Point SAL_CALL getLocation( ) override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen( ) override;
+ virtual css::awt::Size SAL_CALL getSize( ) override;
+ virtual void SAL_CALL grabFocus( ) override;
+ virtual sal_Int32 SAL_CALL getForeground( ) override;
+ virtual sal_Int32 SAL_CALL getBackground( ) override;
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override;
+};
+
#endif // INCLUDED_SVTOOLS_SOURCE_CONTROL_VALUEIMP_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx
index 54d7e3bbbf02..3c8e5cbcc753 100644
--- a/svtools/source/control/valueset.cxx
+++ b/svtools/source/control/valueset.cxx
@@ -2275,4 +2275,1459 @@ void ValueSet::SetEdgeBlending(bool bNew)
}
}
+SvtValueSet::SvtValueSet()
+ : maVirDev( VclPtr<VirtualDevice>::Create())
+ , maColor(COL_TRANSPARENT)
+ , mnStyle(0)
+ , mbFormat(true)
+{
+ maVirDev->SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor());
+
+ mpNoneItem.reset(nullptr);
+
+ mnItemWidth = 0;
+ mnItemHeight = 0;
+ mnTextOffset = 0;
+ mnVisLines = 0;
+ mnLines = 0;
+ mnUserItemWidth = 0;
+ mnUserItemHeight = 0;
+ mnFirstLine = 0;
+ mnSelItemId = 0;
+ mnHighItemId = 0;
+ mnCols = 0;
+ mnCurCol = 0;
+ mnUserCols = 0;
+ mnUserVisLines = 0;
+ mnSpacing = 0;
+ mnFrameStyle = DrawFrameStyle::NONE;
+ mbNoSelection = true;
+ mbBlackSel = false;
+ mbDoubleSel = false;
+ mbScroll = false;
+ mbFullMode = true;
+ mbEdgeBlending = false;
+ mbHasVisibleItems = false;
+}
+
+void SvtValueSet::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ // #106446#, #106601# force mirroring of virtual device
+ maVirDev->EnableRTL(pDrawingArea->get_direction());
+ CustomWidgetController::SetDrawingArea(pDrawingArea);
+}
+
+Reference<XAccessible> SvtValueSet::CreateAccessible()
+{
+ if (!mxAccessible)
+ mxAccessible.set(new SvtValueSetAcc(this));
+ return mxAccessible;
+}
+
+SvtValueSet::~SvtValueSet()
+{
+ Reference<XComponent> xComponent(mxAccessible, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+
+ ImplDeleteItems();
+}
+
+void SvtValueSet::ImplDeleteItems()
+{
+ const size_t n = mItemList.size();
+
+ for ( size_t i = 0; i < n; ++i )
+ {
+ SvtValueSetItem* pItem = mItemList[i];
+ if ( pItem->mbVisible && ImplHasAccessibleListeners() )
+ {
+ Any aOldAny;
+ Any aNewAny;
+
+ aOldAny <<= pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ );
+ ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny);
+ }
+
+ delete pItem;
+ }
+
+ mItemList.clear();
+}
+
+void SvtValueSet::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+void SvtValueSet::UserDraw( const UserDrawEvent& )
+{
+}
+
+size_t SvtValueSet::ImplGetItem( const Point& rPos ) const
+{
+ if (!mbHasVisibleItems)
+ {
+ return VALUESET_ITEM_NOTFOUND;
+ }
+
+ if (mpNoneItem.get() && maNoneItemRect.IsInside(rPos))
+ {
+ return VALUESET_ITEM_NONEITEM;
+ }
+
+ if (maItemListRect.IsInside(rPos))
+ {
+ const int xc = rPos.X() - maItemListRect.Left();
+ const int yc = rPos.Y() - maItemListRect.Top();
+ // The point is inside the area of item list,
+ // let's find the containing item.
+ const int col = xc / (mnItemWidth + mnSpacing);
+ const int x = xc % (mnItemWidth + mnSpacing);
+ const int row = yc / (mnItemHeight + mnSpacing);
+ const int y = yc % (mnItemHeight + mnSpacing);
+
+ if (x < mnItemWidth && y < mnItemHeight)
+ {
+ // the point is inside item rect and not inside spacing
+ const size_t item = (mnFirstLine + row) * static_cast<size_t>(mnCols) + col;
+ if (item < mItemList.size())
+ {
+ return item;
+ }
+ }
+ }
+
+ return VALUESET_ITEM_NOTFOUND;
+}
+
+SvtValueSetItem* SvtValueSet::ImplGetItem( size_t nPos )
+{
+ if (nPos == VALUESET_ITEM_NONEITEM)
+ return mpNoneItem.get();
+ else
+ return (nPos < mItemList.size()) ? mItemList[nPos] : nullptr;
+}
+
+SvtValueSetItem* SvtValueSet::ImplGetFirstItem()
+{
+ return mItemList.size() ? mItemList[0] : nullptr;
+}
+
+sal_uInt16 SvtValueSet::ImplGetVisibleItemCount() const
+{
+ sal_uInt16 nRet = 0;
+ const size_t nItemCount = mItemList.size();
+
+ for ( size_t n = 0; n < nItemCount; ++n )
+ {
+ if ( mItemList[n]->mbVisible )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+void SvtValueSet::ImplFireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue )
+{
+ SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible);
+
+ if( pAcc )
+ pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
+}
+
+bool SvtValueSet::ImplHasAccessibleListeners()
+{
+ SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible);
+ return( pAcc && pAcc->HasAccessibleListeners() );
+}
+
+void SvtValueSet::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ if (GetStyle() & WB_FLATVALUESET)
+ {
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
+ long nOffY = maVirDev->GetOutputSizePixel().Height();
+ Size aWinSize(GetOutputSizePixel());
+ rRenderContext.DrawRect(tools::Rectangle(Point(0, nOffY ), Point( aWinSize.Width(), aWinSize.Height())));
+ }
+
+ ImplDraw(rRenderContext);
+}
+
+void SvtValueSet::GetFocus()
+{
+ SAL_INFO("svtools", "value set getting focus");
+ Invalidate();
+ CustomWidgetController::GetFocus();
+
+ // Tell the accessible object that we got the focus.
+ SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible);
+ if (pAcc)
+ pAcc->GetFocus();
+}
+
+void SvtValueSet::LoseFocus()
+{
+ SAL_INFO("svtools", "value set losing focus");
+ Invalidate();
+ CustomWidgetController::LoseFocus();
+
+ // Tell the accessible object that we lost the focus.
+ SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible);
+ if( pAcc )
+ pAcc->LoseFocus();
+}
+
+void SvtValueSet::Resize()
+{
+ mbFormat = true;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ CustomWidgetController::Resize();
+}
+
+bool SvtValueSet::KeyInput( const KeyEvent& rKeyEvent )
+{
+ size_t nLastItem = mItemList.size();
+
+ if ( !nLastItem || !ImplGetFirstItem() )
+ return CustomWidgetController::KeyInput(rKeyEvent);
+
+ if (mbFormat)
+ Invalidate();
+
+ --nLastItem;
+
+ const size_t nCurPos = mnSelItemId ? GetItemPos(mnSelItemId)
+ : (mpNoneItem.get() ? VALUESET_ITEM_NONEITEM : 0);
+ size_t nItemPos = VALUESET_ITEM_NOTFOUND;
+ size_t nVStep = mnCols;
+
+ switch (rKeyEvent.GetKeyCode().GetCode())
+ {
+ case KEY_HOME:
+ nItemPos = mpNoneItem.get() ? VALUESET_ITEM_NONEITEM : 0;
+ break;
+
+ case KEY_END:
+ nItemPos = nLastItem;
+ break;
+
+ case KEY_LEFT:
+ if (nCurPos != VALUESET_ITEM_NONEITEM)
+ {
+ if (nCurPos)
+ {
+ nItemPos = nCurPos-1;
+ }
+ else if (mpNoneItem.get())
+ {
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ }
+ }
+ break;
+
+ case KEY_RIGHT:
+ if (nCurPos < nLastItem)
+ {
+ if (nCurPos == VALUESET_ITEM_NONEITEM)
+ {
+ nItemPos = 0;
+ }
+ else
+ {
+ nItemPos = nCurPos+1;
+ }
+ }
+ break;
+
+ case KEY_PAGEUP:
+ if (rKeyEvent.GetKeyCode().IsShift() || rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2())
+ {
+ return CustomWidgetController::KeyInput(rKeyEvent);
+ }
+ nVStep *= mnVisLines;
+ SAL_FALLTHROUGH;
+ case KEY_UP:
+ if (nCurPos != VALUESET_ITEM_NONEITEM)
+ {
+ if (nCurPos == nLastItem)
+ {
+ const size_t nCol = mnCols ? nLastItem % mnCols : 0;
+ if (nCol < mnCurCol)
+ {
+ // Move to previous row/page, keeping the old column
+ nVStep -= mnCurCol - nCol;
+ }
+ }
+ if (nCurPos >= nVStep)
+ {
+ // Go up of a whole page
+ nItemPos = nCurPos-nVStep;
+ }
+ else if (mpNoneItem.get())
+ {
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ }
+ else if (nCurPos > mnCols)
+ {
+ // Go to same column in first row
+ nItemPos = nCurPos % mnCols;
+ }
+ }
+ break;
+
+ case KEY_PAGEDOWN:
+ if (rKeyEvent.GetKeyCode().IsShift() || rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2())
+ {
+ return CustomWidgetController::KeyInput(rKeyEvent);
+ }
+ nVStep *= mnVisLines;
+ SAL_FALLTHROUGH;
+ case KEY_DOWN:
+ if (nCurPos != nLastItem)
+ {
+ if (nCurPos == VALUESET_ITEM_NONEITEM)
+ {
+ nItemPos = nVStep-mnCols+mnCurCol;
+ }
+ else
+ {
+ nItemPos = nCurPos+nVStep;
+ }
+ if (nItemPos > nLastItem)
+ {
+ nItemPos = nLastItem;
+ }
+ }
+ break;
+
+ case KEY_RETURN:
+ if (GetStyle() & WB_NO_DIRECTSELECT)
+ {
+ Select();
+ break;
+ }
+ SAL_FALLTHROUGH;
+ default:
+ return CustomWidgetController::KeyInput(rKeyEvent);
+ }
+
+ if ( nItemPos == VALUESET_ITEM_NOTFOUND )
+ return false;
+
+ if ( nItemPos!=VALUESET_ITEM_NONEITEM && nItemPos<nLastItem )
+ {
+ // update current column only in case of a new position
+ // which is also not a "specially" handled one.
+ mnCurCol = mnCols ? nItemPos % mnCols : 0;
+ }
+ const sal_uInt16 nItemId = (nItemPos != VALUESET_ITEM_NONEITEM) ? GetItemId( nItemPos ) : 0;
+ if ( nItemId != mnSelItemId )
+ {
+ SelectItem( nItemId );
+ if (!(GetStyle() & WB_NO_DIRECTSELECT))
+ {
+ // select only if WB_NO_DIRECTSELECT is not set
+ Select();
+ }
+ }
+
+ return true;
+}
+
+void SvtValueSet::MouseButtonDown( const MouseEvent& rMouseEvent )
+{
+ if ( rMouseEvent.IsLeft() )
+ {
+ SvtValueSetItem* pItem = ImplGetItem( ImplGetItem( rMouseEvent.GetPosPixel() ) );
+ if (pItem && !rMouseEvent.IsMod2())
+ {
+ if (rMouseEvent.GetClicks() == 1)
+ {
+ SelectItem( pItem->mnId );
+ if (!(GetStyle() & WB_NOPOINTERFOCUS))
+ GrabFocus();
+ Select();
+ }
+ else if ( rMouseEvent.GetClicks() == 2 )
+ maDoubleClickHdl.Call( this );
+
+ return;
+ }
+ }
+
+ CustomWidgetController::MouseButtonDown( rMouseEvent );
+}
+
+size_t SvtValueSet::GetItemCount() const
+{
+ return mItemList.size();
+}
+
+size_t SvtValueSet::GetItemPos( sal_uInt16 nItemId ) const
+{
+ for ( size_t i = 0, n = mItemList.size(); i < n; ++i ) {
+ if ( mItemList[i]->mnId == nItemId ) {
+ return i;
+ }
+ }
+ return VALUESET_ITEM_NOTFOUND;
+}
+
+sal_uInt16 SvtValueSet::GetItemId( size_t nPos ) const
+{
+ return ( nPos < mItemList.size() ) ? mItemList[nPos]->mnId : 0 ;
+}
+
+sal_uInt16 SvtValueSet::GetItemId( const Point& rPos ) const
+{
+ size_t nItemPos = ImplGetItem( rPos );
+ if ( nItemPos != VALUESET_ITEM_NOTFOUND )
+ return GetItemId( nItemPos );
+
+ return 0;
+}
+
+tools::Rectangle SvtValueSet::GetItemRect( sal_uInt16 nItemId ) const
+{
+ const size_t nPos = GetItemPos( nItemId );
+
+ if ( nPos!=VALUESET_ITEM_NOTFOUND && mItemList[nPos]->mbVisible )
+ return ImplGetItemRect( nPos );
+
+ return tools::Rectangle();
+}
+
+void SvtValueSet::EnableFullItemMode( bool bFullMode )
+{
+ mbFullMode = bFullMode;
+}
+
+tools::Rectangle SvtValueSet::ImplGetItemRect( size_t nPos ) const
+{
+ const size_t nVisibleBegin = static_cast<size_t>(mnFirstLine)*mnCols;
+ const size_t nVisibleEnd = nVisibleBegin + static_cast<size_t>(mnVisLines)*mnCols;
+
+ // Check if the item is inside the range of the displayed ones,
+ // taking into account that last row could be incomplete
+ if ( nPos<nVisibleBegin || nPos>=nVisibleEnd || nPos>=mItemList.size() )
+ return tools::Rectangle();
+
+ nPos -= nVisibleBegin;
+
+ const size_t row = mnCols ? nPos/mnCols : 0;
+ const size_t col = mnCols ? nPos%mnCols : 0;
+ const long x = maItemListRect.Left()+col*(mnItemWidth+mnSpacing);
+ const long y = maItemListRect.Top()+row*(mnItemHeight+mnSpacing);
+
+ return tools::Rectangle( Point(x, y), Size(mnItemWidth, mnItemHeight) );
+}
+
+void SvtValueSet::SetFormat()
+{
+ mbFormat = true;
+}
+
+void SvtValueSet::ImplDraw(vcl::RenderContext& rRenderContext)
+{
+ if (mbFormat)
+ Format(rRenderContext);
+
+ Point aDefPos;
+ Size aSize = maVirDev->GetOutputSizePixel();
+
+ rRenderContext.DrawOutDev(aDefPos, aSize, aDefPos, aSize, *maVirDev.get());
+
+ // draw parting line to the Namefield
+ if (GetStyle() & WB_NAMEFIELD)
+ {
+ if (!(GetStyle() & WB_FLATVALUESET))
+ {
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ Size aWinSize(GetOutputSizePixel());
+ Point aPos1(NAME_LINE_OFF_X, mnTextOffset + NAME_LINE_OFF_Y);
+ Point aPos2(aWinSize.Width() - (NAME_LINE_OFF_X * 2), mnTextOffset + NAME_LINE_OFF_Y);
+ if (!(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono))
+ {
+ rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
+ rRenderContext.DrawLine(aPos1, aPos2);
+ aPos1.AdjustY( 1 );
+ aPos2.AdjustY( 1 );
+ rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
+ }
+ else
+ rRenderContext.SetLineColor(rStyleSettings.GetWindowTextColor());
+ rRenderContext.DrawLine(aPos1, aPos2);
+ }
+ }
+
+ ImplDrawSelect(rRenderContext);
+}
+
+void SvtValueSet::SelectItem( sal_uInt16 nItemId )
+{
+ size_t nItemPos = 0;
+
+ if ( nItemId )
+ {
+ nItemPos = GetItemPos( nItemId );
+ if ( nItemPos == VALUESET_ITEM_NOTFOUND )
+ return;
+ }
+
+ if ( !((mnSelItemId != nItemId) || mbNoSelection) )
+ return;
+
+ sal_uInt16 nOldItem = mnSelItemId ? mnSelItemId : 1;
+ mnSelItemId = nItemId;
+ mbNoSelection = false;
+
+ bool bNewOut = !mbFormat && IsReallyVisible() && IsUpdateMode();
+ bool bNewLine = false;
+
+ // if necessary scroll to the visible area
+ if (mbScroll && nItemId && mnCols)
+ {
+ sal_uInt16 nNewLine = static_cast<sal_uInt16>(nItemPos / mnCols);
+ if ( nNewLine < mnFirstLine )
+ {
+ mnFirstLine = nNewLine;
+ bNewLine = true;
+ }
+ else if ( nNewLine > static_cast<sal_uInt16>(mnFirstLine+mnVisLines-1) )
+ {
+ mnFirstLine = static_cast<sal_uInt16>(nNewLine-mnVisLines+1);
+ bNewLine = true;
+ }
+ }
+
+ if ( bNewOut )
+ {
+ if ( bNewLine )
+ {
+ // redraw everything if the visible area has changed
+ mbFormat = true;
+ }
+ Invalidate();
+ }
+
+ if( ImplHasAccessibleListeners() )
+ {
+ // focus event (deselect)
+ if( nOldItem )
+ {
+ const size_t nPos = GetItemPos( nItemId );
+
+ if( nPos != VALUESET_ITEM_NOTFOUND )
+ {
+ ValueItemAcc* pItemAcc = ValueItemAcc::getImplementation(
+ mItemList[nPos]->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) );
+
+ if( pItemAcc )
+ {
+ Any aOldAny;
+ Any aNewAny;
+ aOldAny <<= Reference<XInterface>(static_cast<cppu::OWeakObject*>(pItemAcc));
+ ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
+ }
+ }
+ }
+
+ // focus event (select)
+ const size_t nPos = GetItemPos( mnSelItemId );
+
+ SvtValueSetItem* pItem;
+ if( nPos != VALUESET_ITEM_NOTFOUND )
+ pItem = mItemList[nPos];
+ else
+ pItem = mpNoneItem.get();
+
+ ValueItemAcc* pItemAcc = nullptr;
+ if (pItem != nullptr)
+ pItemAcc = ValueItemAcc::getImplementation( pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) );
+
+ if( pItemAcc )
+ {
+ Any aOldAny;
+ Any aNewAny;
+ aNewAny <<= Reference<XInterface>(static_cast<cppu::OWeakObject*>(pItemAcc));
+ ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny);
+ }
+
+ // selection event
+ Any aOldAny;
+ Any aNewAny;
+ ImplFireAccessibleEvent(AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny);
+ }
+ maHighlightHdl.Call(this);
+}
+
+void SvtValueSet::SetNoSelection()
+{
+ mbNoSelection = true;
+
+ if (IsReallyVisible() && IsUpdateMode())
+ Invalidate();
+}
+
+void SvtValueSet::Format(vcl::RenderContext const & rRenderContext)
+{
+ Size aWinSize(GetOutputSizePixel());
+ size_t nItemCount = mItemList.size();
+ WinBits nStyle = GetStyle();
+ long nTxtHeight = rRenderContext.GetTextHeight();
+ long nOff;
+ long nNoneHeight;
+ long nNoneSpace;
+
+ // calculate item offset
+ if (nStyle & WB_ITEMBORDER)
+ {
+ if (nStyle & WB_DOUBLEBORDER)
+ nOff = ITEM_OFFSET_DOUBLE;
+ else
+ nOff = ITEM_OFFSET;
+ }
+ else
+ nOff = 0;
+
+ // consider size, if NameField does exist
+ if (nStyle & WB_NAMEFIELD)
+ {
+ mnTextOffset = aWinSize.Height() - nTxtHeight - NAME_OFFSET;
+ aWinSize.AdjustHeight( -(nTxtHeight + NAME_OFFSET) );
+
+ if (!(nStyle & WB_FLATVALUESET))
+ {
+ mnTextOffset -= NAME_LINE_HEIGHT + NAME_LINE_OFF_Y;
+ aWinSize.AdjustHeight( -(NAME_LINE_HEIGHT + NAME_LINE_OFF_Y) );
+ }
+ }
+ else
+ mnTextOffset = 0;
+
+ // consider offset and size, if NoneField does exist
+ if (nStyle & WB_NONEFIELD)
+ {
+ nNoneHeight = nTxtHeight + nOff;
+ nNoneSpace = mnSpacing;
+ }
+ else
+ {
+ nNoneHeight = 0;
+ nNoneSpace = 0;
+
+ if (mpNoneItem.get())
+ mpNoneItem.reset(nullptr);
+ }
+
+ // calculate number of columns
+ if (!mnUserCols)
+ {
+ if (mnUserItemWidth)
+ {
+ mnCols = static_cast<sal_uInt16>((aWinSize.Width() - mnSpacing) / (mnUserItemWidth + mnSpacing));
+ if (mnCols <= 0)
+ mnCols = 1;
+ }
+ else
+ {
+ mnCols = 1;
+ }
+ }
+ else
+ {
+ mnCols = mnUserCols;
+ }
+
+ // calculate number of rows
+ mbScroll = false;
+
+ // Floor( (M+N-1)/N )==Ceiling( M/N )
+ mnLines = (static_cast<long>(nItemCount) + mnCols - 1) / mnCols;
+ if (mnLines <= 0)
+ mnLines = 1;
+
+ long nCalcHeight = aWinSize.Height() - nNoneHeight;
+ if (mnUserVisLines)
+ {
+ mnVisLines = mnUserVisLines;
+ }
+ else if (mnUserItemHeight)
+ {
+ mnVisLines = (nCalcHeight - nNoneSpace + mnSpacing) / (mnUserItemHeight + mnSpacing);
+ if (!mnVisLines)
+ mnVisLines = 1;
+ }
+ else
+ {
+ mnVisLines = mnLines;
+ }
+
+ if (mnLines > mnVisLines)
+ mbScroll = true;
+
+ if (mnLines <= mnVisLines)
+ {
+ mnFirstLine = 0;
+ }
+ else
+ {
+ if (mnFirstLine > static_cast<sal_uInt16>(mnLines - mnVisLines))
+ mnFirstLine = static_cast<sal_uInt16>(mnLines - mnVisLines);
+ }
+
+ // calculate item size
+ const long nColSpace = (mnCols - 1) * static_cast<long>(mnSpacing);
+ const long nLineSpace = ((mnVisLines - 1) * mnSpacing) + nNoneSpace;
+ if (mnUserItemWidth && !mnUserCols)
+ {
+ mnItemWidth = mnUserItemWidth;
+ if (mnItemWidth > aWinSize.Width() - nColSpace)
+ mnItemWidth = aWinSize.Width() - nColSpace;
+ }
+ else
+ mnItemWidth = (aWinSize.Width() - nColSpace) / mnCols;
+ if (mnUserItemHeight && !mnUserVisLines)
+ {
+ mnItemHeight = mnUserItemHeight;
+ if (mnItemHeight > nCalcHeight - nNoneSpace)
+ mnItemHeight = nCalcHeight - nNoneSpace;
+ }
+ else
+ {
+ nCalcHeight -= nLineSpace;
+ mnItemHeight = nCalcHeight / mnVisLines;
+ }
+
+ // Init VirDev
+ maVirDev->SetSettings(rRenderContext.GetSettings());
+ maVirDev->SetOutputSizePixel(aWinSize);
+
+ // nothing is changed in case of too small items
+ if ((mnItemWidth <= 0) ||
+ (mnItemHeight <= ((nStyle & WB_ITEMBORDER) ? 4 : 2)) ||
+ !nItemCount)
+ {
+ mbHasVisibleItems = false;
+
+ if (nStyle & WB_NONEFIELD)
+ {
+ if (mpNoneItem.get())
+ {
+ mpNoneItem->mbVisible = false;
+ mpNoneItem->maText = GetText();
+ }
+ }
+
+ for (size_t i = 0; i < nItemCount; i++)
+ {
+ mItemList[i]->mbVisible = false;
+ }
+ }
+ else
+ {
+ mbHasVisibleItems = true;
+
+ // determine Frame-Style
+ if (nStyle & WB_DOUBLEBORDER)
+ mnFrameStyle = DrawFrameStyle::DoubleIn;
+ else
+ mnFrameStyle = DrawFrameStyle::In;
+
+ // determine selected color and width
+ // if necessary change the colors, to make the selection
+ // better detectable
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ Color aHighColor(rStyleSettings.GetHighlightColor());
+ if (((aHighColor.GetRed() > 0x80) || (aHighColor.GetGreen() > 0x80) ||
+ (aHighColor.GetBlue() > 0x80)) ||
+ ((aHighColor.GetRed() == 0x80) && (aHighColor.GetGreen() == 0x80) &&
+ (aHighColor.GetBlue() == 0x80)))
+ {
+ mbBlackSel = true;
+ }
+ else
+ {
+ mbBlackSel = false;
+ }
+ // draw the selection with double width if the items are bigger
+ if ((nStyle & WB_DOUBLEBORDER) &&
+ ((mnItemWidth >= 25) && (mnItemHeight >= 20)))
+ {
+ mbDoubleSel = true;
+ }
+ else
+ {
+ mbDoubleSel = false;
+ }
+
+ // calculate offsets
+ long nStartX;
+ long nStartY;
+ if (mbFullMode)
+ {
+ long nAllItemWidth = (mnItemWidth * mnCols) + nColSpace;
+ long nAllItemHeight = (mnItemHeight * mnVisLines) + nNoneHeight + nLineSpace;
+ nStartX = (aWinSize.Width() - nAllItemWidth) / 2;
+ nStartY = (aWinSize.Height() - nAllItemHeight) / 2;
+ }
+ else
+ {
+ nStartX = 0;
+ nStartY = 0;
+ }
+
+ // calculate and draw items
+ maVirDev->SetLineColor();
+ long x = nStartX;
+ long y = nStartY;
+
+ // create NoSelection field and show it
+ if (nStyle & WB_NONEFIELD)
+ {
+ if (!mpNoneItem)
+ mpNoneItem.reset(new SvtValueSetItem(*this));
+
+ mpNoneItem->mnId = 0;
+ mpNoneItem->meType = VALUESETITEM_NONE;
+ mpNoneItem->mbVisible = true;
+ maNoneItemRect.SetLeft( x );
+ maNoneItemRect.SetTop( y );
+ maNoneItemRect.SetRight( maNoneItemRect.Left() + aWinSize.Width() - x - 1 );
+ maNoneItemRect.SetBottom( y + nNoneHeight - 1 );
+
+ ImplFormatItem(rRenderContext, mpNoneItem.get(), maNoneItemRect);
+
+ y += nNoneHeight + nNoneSpace;
+ }
+
+ // draw items
+ sal_uLong nFirstItem = static_cast<sal_uLong>(mnFirstLine) * mnCols;
+ sal_uLong nLastItem = nFirstItem + (mnVisLines * mnCols);
+
+ maItemListRect.SetLeft( x );
+ maItemListRect.SetTop( y );
+ maItemListRect.SetRight( x + mnCols * (mnItemWidth + mnSpacing) - mnSpacing - 1 );
+ maItemListRect.SetBottom( y + mnVisLines * (mnItemHeight + mnSpacing) - mnSpacing - 1 );
+
+ if (!mbFullMode)
+ {
+ // If want also draw parts of items in the last line,
+ // then we add one more line if parts of these line are
+ // visible
+ if (y + (mnVisLines * (mnItemHeight + mnSpacing)) < aWinSize.Height())
+ nLastItem += mnCols;
+ maItemListRect.SetBottom( aWinSize.Height() - y );
+ }
+ for (size_t i = 0; i < nItemCount; i++)
+ {
+ SvtValueSetItem* pItem = mItemList[i];
+
+ if (i >= nFirstItem && i < nLastItem)
+ {
+ if (!pItem->mbVisible && ImplHasAccessibleListeners())
+ {
+ Any aOldAny;
+ Any aNewAny;
+
+ aNewAny <<= pItem->GetAccessible(false/*bIsTransientChildrenDisabled*/);
+ ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny);
+ }
+
+ pItem->mbVisible = true;
+ ImplFormatItem(rRenderContext, pItem, tools::Rectangle(Point(x, y), Size(mnItemWidth, mnItemHeight)));
+
+ if (!((i + 1) % mnCols))
+ {
+ x = nStartX;
+ y += mnItemHeight + mnSpacing;
+ }
+ else
+ x += mnItemWidth + mnSpacing;
+ }
+ else
+ {
+ if (pItem->mbVisible && ImplHasAccessibleListeners())
+ {
+ Any aOldAny;
+ Any aNewAny;
+
+ aOldAny <<= pItem->GetAccessible(false/*bIsTransientChildrenDisabled*/);
+ ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny);
+ }
+
+ pItem->mbVisible = false;
+ }
+ }
+ }
+
+ // waiting for the next since the formatting is finished
+ mbFormat = false;
+}
+
+void SvtValueSet::ImplDrawSelect(vcl::RenderContext& rRenderContext)
+{
+ if (!IsReallyVisible())
+ return;
+
+ const bool bFocus = HasFocus();
+ if (!bFocus && mbNoSelection)
+ {
+ ImplDrawItemText(rRenderContext, OUString());
+ return;
+ }
+
+ ImplDrawSelect(rRenderContext, mnSelItemId, bFocus, !mbNoSelection);
+}
+
+void SvtValueSet::ImplDrawSelect(vcl::RenderContext& rRenderContext, sal_uInt16 nItemId, const bool bFocus, const bool bDrawSel )
+{
+ SvtValueSetItem* pItem;
+ tools::Rectangle aRect;
+ if (nItemId)
+ {
+ const size_t nPos = GetItemPos( nItemId );
+ pItem = mItemList[ nPos ];
+ aRect = ImplGetItemRect( nPos );
+ }
+ else if (mpNoneItem.get())
+ {
+ pItem = mpNoneItem.get();
+ aRect = maNoneItemRect;
+ }
+ else if (bFocus && (pItem = ImplGetFirstItem()))
+ {
+ aRect = ImplGetItemRect(0);
+ }
+ else
+ {
+ return;
+ }
+
+ if (!pItem->mbVisible)
+ return;
+
+ // draw selection
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ rRenderContext.SetFillColor();
+
+ Color aDoubleColor(rStyleSettings.GetHighlightColor());
+ Color aSingleColor(rStyleSettings.GetHighlightTextColor());
+ if (!mbDoubleSel)
+ {
+ /*
+ * #99777# contrast enhancement for thin mode
+ */
+ const Wallpaper& rWall = maVirDev->GetBackground();
+ if (!rWall.IsBitmap() && ! rWall.IsGradient())
+ {
+ const Color& rBack = rWall.GetColor();
+ if (rBack.IsDark() && ! aDoubleColor.IsBright())
+ {
+ aDoubleColor = COL_WHITE;
+ aSingleColor = COL_BLACK;
+ }
+ else if (rBack.IsBright() && !aDoubleColor.IsDark())
+ {
+ aDoubleColor = COL_BLACK;
+ aSingleColor = COL_WHITE;
+ }
+ }
+ }
+
+ // specify selection output
+ WinBits nStyle = GetStyle();
+ if (nStyle & WB_MENUSTYLEVALUESET)
+ {
+ if (bDrawSel)
+ {
+ rRenderContext.SetLineColor(mbBlackSel ? COL_BLACK : aDoubleColor);
+ rRenderContext.DrawRect(aRect);
+ }
+ }
+ else
+ {
+ if (bDrawSel)
+ {
+ rRenderContext.SetLineColor(mbBlackSel ? COL_BLACK : aDoubleColor);
+ rRenderContext.DrawRect(aRect);
+ }
+ if (mbDoubleSel)
+ {
+ aRect.AdjustLeft( 1 );
+ aRect.AdjustTop( 1 );
+ aRect.AdjustRight( -1 );
+ aRect.AdjustBottom( -1 );
+ if (bDrawSel)
+ rRenderContext.DrawRect(aRect);
+ }
+ aRect.AdjustLeft( 1 );
+ aRect.AdjustTop( 1 );
+ aRect.AdjustRight( -1 );
+ aRect.AdjustBottom( -1 );
+ tools::Rectangle aRect2 = aRect;
+ aRect.AdjustLeft( 1 );
+ aRect.AdjustTop( 1 );
+ aRect.AdjustRight( -1 );
+ aRect.AdjustBottom( -1 );
+ if (bDrawSel)
+ rRenderContext.DrawRect(aRect);
+ if (mbDoubleSel)
+ {
+ aRect.AdjustLeft( 1 );
+ aRect.AdjustTop( 1 );
+ aRect.AdjustRight( -1 );
+ aRect.AdjustBottom( -1 );
+ if (bDrawSel)
+ rRenderContext.DrawRect(aRect);
+ }
+
+ if (bDrawSel)
+ {
+ rRenderContext.SetLineColor(mbBlackSel ? COL_WHITE : aSingleColor);
+ }
+ else
+ {
+ rRenderContext.SetLineColor(COL_LIGHTGRAY);
+ }
+ rRenderContext.DrawRect(aRect2);
+ }
+
+ ImplDrawItemText(rRenderContext, pItem->maText);
+}
+
+void SvtValueSet::ImplFormatItem(vcl::RenderContext const & rRenderContext, SvtValueSetItem* pItem, tools::Rectangle aRect)
+{
+ WinBits nStyle = GetStyle();
+ if (nStyle & WB_ITEMBORDER)
+ {
+ aRect.AdjustLeft(1 );
+ aRect.AdjustTop(1 );
+ aRect.AdjustRight( -1 );
+ aRect.AdjustBottom( -1 );
+
+ if (nStyle & WB_FLATVALUESET)
+ {
+ sal_Int32 nBorder = (nStyle & WB_DOUBLEBORDER) ? 2 : 1;
+
+ aRect.AdjustLeft(nBorder );
+ aRect.AdjustTop(nBorder );
+ aRect.AdjustRight( -nBorder );
+ aRect.AdjustBottom( -nBorder );
+ }
+ else
+ {
+ DecorationView aView(maVirDev.get());
+ aRect = aView.DrawFrame(aRect, mnFrameStyle);
+ }
+ }
+
+ if (pItem == mpNoneItem.get())
+ pItem->maText = GetText();
+
+ if (!((aRect.GetHeight() > 0) && (aRect.GetWidth() > 0)))
+ return;
+
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+
+ if (pItem == mpNoneItem.get())
+ {
+ maVirDev->SetFont(rRenderContext.GetFont());
+ maVirDev->SetTextColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor());
+ maVirDev->SetTextFillColor();
+ maVirDev->SetFillColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuColor() : rStyleSettings.GetWindowColor());
+ maVirDev->DrawRect(aRect);
+ Point aTxtPos(aRect.Left() + 2, aRect.Top());
+ long nTxtWidth = rRenderContext.GetTextWidth(pItem->maText);
+ if ((aTxtPos.X() + nTxtWidth) > aRect.Right())
+ {
+ maVirDev->SetClipRegion(vcl::Region(aRect));
+ maVirDev->DrawText(aTxtPos, pItem->maText);
+ maVirDev->SetClipRegion();
+ }
+ else
+ maVirDev->DrawText(aTxtPos, pItem->maText);
+ }
+ else if (pItem->meType == VALUESETITEM_COLOR)
+ {
+ maVirDev->SetFillColor(pItem->maColor);
+ maVirDev->DrawRect(aRect);
+ }
+ else
+ {
+ if (IsColor())
+ maVirDev->SetFillColor(maColor);
+ else if (nStyle & WB_MENUSTYLEVALUESET)
+ maVirDev->SetFillColor(rStyleSettings.GetMenuColor());
+ else if (IsEnabled())
+ maVirDev->SetFillColor(rStyleSettings.GetWindowColor());
+ else
+ maVirDev->SetFillColor(rStyleSettings.GetFaceColor());
+ maVirDev->DrawRect(aRect);
+
+ if (pItem->meType == VALUESETITEM_USERDRAW)
+ {
+ UserDrawEvent aUDEvt(nullptr, maVirDev.get(), aRect, pItem->mnId);
+ UserDraw(aUDEvt);
+ }
+ else
+ {
+ Size aImageSize = pItem->maImage.GetSizePixel();
+ Size aRectSize = aRect.GetSize();
+ Point aPos(aRect.Left(), aRect.Top());
+ aPos.AdjustX((aRectSize.Width() - aImageSize.Width()) / 2 );
+
+ if (pItem->meType != VALUESETITEM_IMAGE_AND_TEXT)
+ aPos.AdjustY((aRectSize.Height() - aImageSize.Height()) / 2 );
+
+ DrawImageFlags nImageStyle = DrawImageFlags::NONE;
+ if (!IsEnabled())
+ nImageStyle |= DrawImageFlags::Disable;
+
+ if (aImageSize.Width() > aRectSize.Width() ||
+ aImageSize.Height() > aRectSize.Height())
+ {
+ maVirDev->SetClipRegion(vcl::Region(aRect));
+ maVirDev->DrawImage(aPos, pItem->maImage, nImageStyle);
+ maVirDev->SetClipRegion();
+ }
+ else
+ maVirDev->DrawImage(aPos, pItem->maImage, nImageStyle);
+
+ if (pItem->meType == VALUESETITEM_IMAGE_AND_TEXT)
+ {
+ maVirDev->SetFont(rRenderContext.GetFont());
+ maVirDev->SetTextColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor());
+ maVirDev->SetTextFillColor();
+
+ long nTxtWidth = maVirDev->GetTextWidth(pItem->maText);
+
+ if (nTxtWidth > aRect.GetWidth())
+ maVirDev->SetClipRegion(vcl::Region(aRect));
+
+ maVirDev->DrawText(Point(aRect.Left() +
+ (aRect.GetWidth() - nTxtWidth) / 2,
+ aRect.Bottom() - maVirDev->GetTextHeight()),
+ pItem->maText);
+
+ if (nTxtWidth > aRect.GetWidth())
+ maVirDev->SetClipRegion();
+ }
+ }
+ }
+
+ const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
+
+ if (nEdgeBlendingPercent)
+ {
+ const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
+ const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
+ const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
+ const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));
+
+ if (!aBlendFrame.IsEmpty())
+ {
+ maVirDev->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
+ }
+ }
+}
+
+void SvtValueSet::ImplDrawItemText(vcl::RenderContext& rRenderContext, const OUString& rText)
+{
+ if (!(GetStyle() & WB_NAMEFIELD))
+ return;
+
+ Size aWinSize(GetOutputSizePixel());
+ long nTxtWidth = rRenderContext.GetTextWidth(rText);
+ long nTxtOffset = mnTextOffset;
+
+ // delete rectangle and show text
+ if (GetStyle() & WB_FLATVALUESET)
+ {
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
+ rRenderContext.DrawRect(tools::Rectangle(Point(0, nTxtOffset), Point(aWinSize.Width(), aWinSize.Height())));
+ rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor());
+ }
+ else
+ {
+ nTxtOffset += NAME_LINE_HEIGHT+NAME_LINE_OFF_Y;
+ rRenderContext.SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor());
+ rRenderContext.Erase(tools::Rectangle(Point(0, nTxtOffset), Point(aWinSize.Width(), aWinSize.Height())));
+ }
+ rRenderContext.DrawText(Point((aWinSize.Width() - nTxtWidth) / 2, nTxtOffset + (NAME_OFFSET / 2)), rText);
+}
+
+bool SvtValueSet::ImplScroll(const Point& rPos)
+{
+ if (!mbScroll || !maItemListRect.IsInside(rPos))
+ return false;
+
+ const long nScrollOffset = (mnItemHeight <= 16) ? SCROLL_OFFSET / 2 : SCROLL_OFFSET;
+ bool bScroll = false;
+
+ if (rPos.Y() <= maItemListRect.Top() + nScrollOffset)
+ {
+ if (mnFirstLine > 0)
+ {
+ --mnFirstLine;
+ bScroll = true;
+ }
+ }
+ else if (rPos.Y() >= maItemListRect.Bottom() - nScrollOffset)
+ {
+ if (mnFirstLine < static_cast<sal_uInt16>(mnLines - mnVisLines))
+ {
+ ++mnFirstLine;
+ bScroll = true;
+ }
+ }
+
+ if (!bScroll)
+ return false;
+
+ mbFormat = true;
+ Invalidate();
+ return true;
+}
+
+void SvtValueSet::StyleUpdated()
+{
+ mbFormat = true;
+ Invalidate();
+}
+
+void SvtValueSet::SetColCount( sal_uInt16 nNewCols )
+{
+ if ( mnUserCols != nNewCols )
+ {
+ mnUserCols = nNewCols;
+ mbFormat = true;
+ queue_resize();
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+Color SvtValueSet::GetItemColor( sal_uInt16 nItemId ) const
+{
+ size_t nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mItemList[nPos]->maColor;
+ else
+ return Color();
+}
+
+Size SvtValueSet::CalcWindowSizePixel( const Size& rItemSize, sal_uInt16 nDesireCols,
+ sal_uInt16 nDesireLines ) const
+{
+ size_t nCalcCols = nDesireCols;
+ size_t nCalcLines = nDesireLines;
+
+ if ( !nCalcCols )
+ {
+ if ( mnUserCols )
+ nCalcCols = mnUserCols;
+ else
+ nCalcCols = 1;
+ }
+
+ if ( !nCalcLines )
+ {
+ nCalcLines = mnVisLines;
+
+ if ( mbFormat )
+ {
+ if ( mnUserVisLines )
+ nCalcLines = mnUserVisLines;
+ else
+ {
+ // Floor( (M+N-1)/N )==Ceiling( M/N )
+ nCalcLines = (mItemList.size()+nCalcCols-1) / nCalcCols;
+ if ( !nCalcLines )
+ nCalcLines = 1;
+ }
+ }
+ }
+
+ Size aSize( rItemSize.Width() * nCalcCols, rItemSize.Height() * nCalcLines );
+ WinBits nStyle = GetStyle();
+ long nTxtHeight = GetTextHeight();
+ long n;
+
+ if ( nStyle & WB_ITEMBORDER )
+ {
+ if ( nStyle & WB_DOUBLEBORDER )
+ n = ITEM_OFFSET_DOUBLE;
+ else
+ n = ITEM_OFFSET;
+
+ aSize.AdjustWidth(n * nCalcCols );
+ aSize.AdjustHeight(n * nCalcLines );
+ }
+ else
+ n = 0;
+
+ if ( mnSpacing )
+ {
+ aSize.AdjustWidth(mnSpacing * (nCalcCols - 1) );
+ aSize.AdjustHeight(mnSpacing * (nCalcLines - 1) );
+ }
+
+ if ( nStyle & WB_NAMEFIELD )
+ {
+ aSize.AdjustHeight(nTxtHeight + NAME_OFFSET );
+ if ( !(nStyle & WB_FLATVALUESET) )
+ aSize.AdjustHeight(NAME_LINE_HEIGHT + NAME_LINE_OFF_Y );
+ }
+
+ if ( nStyle & WB_NONEFIELD )
+ {
+ aSize.AdjustHeight(nTxtHeight + n + mnSpacing );
+ }
+
+ return aSize;
+}
+
+void SvtValueSet::InsertItem( sal_uInt16 nItemId, const Color& rColor,
+ const OUString& rText )
+{
+ SvtValueSetItem* pItem = new SvtValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_COLOR;
+ pItem->maColor = rColor;
+ pItem->maText = rText;
+ ImplInsertItem( pItem, VALUESET_APPEND );
+}
+
+void SvtValueSet::ImplInsertItem( SvtValueSetItem *const pItem, const size_t nPos )
+{
+ DBG_ASSERT( pItem->mnId, "ValueSet::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( pItem->mnId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertItem(): ItemId already exists" );
+
+ if ( nPos < mItemList.size() ) {
+ SvtValueItemList::iterator it = mItemList.begin();
+ ::std::advance( it, nPos );
+ mItemList.insert( it, pItem );
+ } else {
+ mItemList.push_back( pItem );
+ }
+
+ queue_resize();
+
+ mbFormat = true;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+void SvtValueSet::SetEdgeBlending(bool bNew)
+{
+ if(mbEdgeBlending != bNew)
+ {
+ mbEdgeBlending = bNew;
+ mbFormat = true;
+
+ if (GetDrawingArea() && IsReallyVisible() && IsUpdateMode())
+ {
+ Invalidate();
+ }
+ }
+}
+
+Size SvtValueSet::CalcItemSizePixel( const Size& rItemSize) const
+{
+ Size aSize = rItemSize;
+
+ WinBits nStyle = GetStyle();
+ if ( nStyle & WB_ITEMBORDER )
+ {
+ long n;
+
+ if ( nStyle & WB_DOUBLEBORDER )
+ n = ITEM_OFFSET_DOUBLE;
+ else
+ n = ITEM_OFFSET;
+
+ aSize.AdjustWidth(n );
+ aSize.AdjustHeight(n );
+ }
+
+ return aSize;
+}
+
+void SvtValueSet::SetLineCount( sal_uInt16 nNewLines )
+{
+ if ( mnUserVisLines != nNewLines )
+ {
+ mnUserVisLines = nNewLines;
+ mbFormat = true;
+ queue_resize();
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+void SvtValueSet::SetItemWidth( long nNewItemWidth )
+{
+ if ( mnUserItemWidth != nNewItemWidth )
+ {
+ mnUserItemWidth = nNewItemWidth;
+ mbFormat = true;
+ queue_resize();
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+void SvtValueSet::SetItemHeight( long nNewItemHeight )
+{
+ if ( mnUserItemHeight != nNewItemHeight )
+ {
+ mnUserItemHeight = nNewItemHeight;
+ mbFormat = true;
+ queue_resize();
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+OUString SvtValueSet::RequestHelp(tools::Rectangle& rHelpRect)
+{
+ Point aPos = rHelpRect.TopLeft();
+ const size_t nItemPos = ImplGetItem( aPos );
+ OUString sRet;
+ if (nItemPos != VALUESET_ITEM_NOTFOUND)
+ {
+ rHelpRect = ImplGetItemRect(nItemPos);
+ sRet = GetItemText(ImplGetItem(nItemPos)->mnId);
+ }
+ return sRet;
+}
+
+OUString SvtValueSet::GetItemText(sal_uInt16 nItemId) const
+{
+ const size_t nPos = GetItemPos(nItemId);
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mItemList[nPos]->maText;
+
+ return OUString();
+}
+
+void SvtValueSet::SetColor(const Color& rColor)
+{
+ maColor = rColor;
+ mbFormat = true;
+ if (IsReallyVisible() && IsUpdateMode())
+ Invalidate();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */