LCOV - code coverage report
Current view: top level - svx/source/form - fmcontrolbordermanager.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 32 179 17.9 %
Date: 2015-06-13 12:38:46 Functions: 7 22 31.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "fmcontrolbordermanager.hxx"
      22             : 
      23             : #include "fmprop.hrc"
      24             : 
      25             : #include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
      26             : #include <com/sun/star/awt/XTextComponent.hpp>
      27             : #include <com/sun/star/awt/XListBox.hpp>
      28             : #include <tools/debug.hxx>
      29             : #include <osl/diagnose.h>
      30             : 
      31             : 
      32             : namespace svxform
      33             : {
      34             : 
      35             : 
      36             :     using namespace ::com::sun::star::uno;
      37             :     using namespace ::com::sun::star::awt;
      38             :     using namespace ::com::sun::star::form::validation;
      39             : 
      40             : 
      41             :     //= helper
      42             : 
      43             : 
      44           0 :     static void setUnderline( const Reference< XVclWindowPeer >& _rxPeer, const UnderlineDescriptor& _rUnderline )
      45             :     {
      46             :         OSL_ENSURE( _rxPeer.is(), "setUnderline: invalid peer!" );
      47             : 
      48             :         // the underline type is an aspect of the font
      49           0 :         FontDescriptor aFont;
      50           0 :         OSL_VERIFY( _rxPeer->getProperty( FM_PROP_FONT ) >>= aFont );
      51           0 :         aFont.Underline = _rUnderline.nUnderlineType;
      52           0 :         _rxPeer->setProperty( FM_PROP_FONT, makeAny( aFont ) );
      53             :         // the underline color is a separate property
      54           0 :         _rxPeer->setProperty( FM_PROP_TEXTLINECOLOR, makeAny( _rUnderline.nUnderlineColor ) );
      55           0 :     }
      56             : 
      57             : 
      58           0 :     static void getUnderline( const Reference< XVclWindowPeer >& _rxPeer, UnderlineDescriptor& _rUnderline )
      59             :     {
      60             :         OSL_ENSURE( _rxPeer.is(), "getUnderline: invalid peer!" );
      61             : 
      62           0 :         FontDescriptor aFont;
      63           0 :         OSL_VERIFY( _rxPeer->getProperty( FM_PROP_FONT ) >>= aFont );
      64           0 :         _rUnderline.nUnderlineType = aFont.Underline;
      65             : 
      66           0 :         OSL_VERIFY( _rxPeer->getProperty( FM_PROP_TEXTLINECOLOR ) >>= _rUnderline.nUnderlineColor );
      67           0 :     }
      68             : 
      69             : 
      70           0 :     static void getBorder( const Reference< XVclWindowPeer >& _rxPeer, BorderDescriptor& _rBoder )
      71             :     {
      72             :         OSL_ENSURE( _rxPeer.is(), "getBorder: invalid peer!" );
      73             : 
      74           0 :         OSL_VERIFY( _rxPeer->getProperty( FM_PROP_BORDER ) >>= _rBoder.nBorderType );
      75           0 :         OSL_VERIFY( _rxPeer->getProperty( FM_PROP_BORDERCOLOR ) >>= _rBoder.nBorderColor );
      76           0 :     }
      77             : 
      78             : 
      79           0 :     static void setBorder( const Reference< XVclWindowPeer >& _rxPeer, const BorderDescriptor& _rBoder )
      80             :     {
      81             :         OSL_ENSURE( _rxPeer.is(), "setBorder: invalid peer!" );
      82             : 
      83           0 :         _rxPeer->setProperty( FM_PROP_BORDER, makeAny( _rBoder.nBorderType ) );
      84           0 :         _rxPeer->setProperty( FM_PROP_BORDERCOLOR, makeAny( _rBoder.nBorderColor ) );
      85           0 :     }
      86             : 
      87          95 :     ControlBorderManager::ControlBorderManager()
      88             :         :m_nFocusColor    ( 0x000000FF )
      89             :         ,m_nMouseHoveColor( 0x007098BE )
      90             :         ,m_nInvalidColor  ( 0x00FF0000 )
      91          95 :         ,m_bDynamicBorderColors( false )
      92             :     {
      93          95 :     }
      94             : 
      95             : 
      96          95 :     ControlBorderManager::~ControlBorderManager()
      97             :     {
      98          95 :     }
      99             : 
     100             : 
     101           0 :     bool ControlBorderManager::canColorBorder( const Reference< XVclWindowPeer >& _rxPeer )
     102             :     {
     103             :         OSL_PRECOND( _rxPeer.is(), "ControlBorderManager::canColorBorder: invalid peer!" );
     104             : 
     105           0 :         PeerBag::const_iterator aPos = m_aColorableControls.find( _rxPeer );
     106           0 :         if ( aPos != m_aColorableControls.end() )
     107           0 :             return true;
     108             : 
     109           0 :         aPos = m_aNonColorableControls.find( _rxPeer );
     110           0 :         if ( aPos != m_aNonColorableControls.end() )
     111           0 :             return false;
     112             : 
     113             :         // this peer is not yet known
     114             : 
     115             :         // no border coloring for controls which are not for text input
     116             :         // #i37434# / 2004-11-19 / frank.schoenheit@sun.com
     117           0 :         Reference< XTextComponent > xText( _rxPeer, UNO_QUERY );
     118           0 :         Reference< XListBox > xListBox( _rxPeer, UNO_QUERY );
     119           0 :         if ( xText.is() || xListBox.is() )
     120             :         {
     121           0 :             sal_Int16 nBorderStyle = VisualEffect::NONE;
     122           0 :             OSL_VERIFY( _rxPeer->getProperty( FM_PROP_BORDER ) >>= nBorderStyle );
     123           0 :             if ( nBorderStyle == VisualEffect::FLAT )
     124             :                 // if you change this to also accept LOOK3D, then this would also work, but look ugly
     125             :             {
     126           0 :                 m_aColorableControls.insert( _rxPeer );
     127           0 :                 return true;
     128             :             }
     129             :         }
     130             : 
     131           0 :         m_aNonColorableControls.insert( _rxPeer );
     132           0 :         return false;
     133             :     }
     134             : 
     135             : 
     136           0 :     ControlStatus ControlBorderManager::getControlStatus( const Reference< XControl >& _rxControl )
     137             :     {
     138           0 :         ControlStatus nStatus = CONTROL_STATUS_NONE;
     139             : 
     140           0 :         if ( _rxControl.get() == m_aFocusControl.xControl.get() )
     141           0 :             nStatus |= CONTROL_STATUS_FOCUSED;
     142             : 
     143           0 :         if ( _rxControl.get() == m_aMouseHoverControl.xControl.get() )
     144           0 :             nStatus |= CONTROL_STATUS_MOUSE_HOVER;
     145             : 
     146           0 :         if ( m_aInvalidControls.find( ControlData( _rxControl ) ) != m_aInvalidControls.end() )
     147           0 :             nStatus |= CONTROL_STATUS_INVALID;
     148             : 
     149           0 :         return nStatus;
     150             :     }
     151             : 
     152             : 
     153           0 :     sal_Int32 ControlBorderManager::getControlColorByStatus( ControlStatus _nStatus )
     154             :     {
     155             :         // "invalid" is ranked highest
     156           0 :         if ( _nStatus & CONTROL_STATUS_INVALID )
     157           0 :             return m_nInvalidColor;
     158             : 
     159             :         // then, "focused" is more important than ...
     160           0 :         if ( _nStatus & CONTROL_STATUS_FOCUSED )
     161           0 :             return m_nFocusColor;
     162             : 
     163             :         // ... "mouse over"
     164           0 :         if ( _nStatus & CONTROL_STATUS_MOUSE_HOVER )
     165           0 :             return m_nMouseHoveColor;
     166             : 
     167             :         OSL_FAIL( "ControlBorderManager::getControlColorByStatus: invalid status!" );
     168           0 :         return 0x00000000;
     169             :     }
     170             : 
     171             : 
     172           0 :     void ControlBorderManager::updateBorderStyle( const Reference< XControl >& _rxControl, const Reference< XVclWindowPeer >& _rxPeer, const BorderDescriptor& _rFallback )
     173             :     {
     174             :         OSL_PRECOND( _rxControl.is() && _rxPeer.is(), "ControlBorderManager::updateBorderStyle: invalid parameters!" );
     175             : 
     176           0 :         ControlStatus nStatus = getControlStatus( _rxControl );
     177           0 :         BorderDescriptor aBorder;
     178             :         aBorder.nBorderType =   ( nStatus == CONTROL_STATUS_NONE )
     179             :                             ?   _rFallback.nBorderType
     180           0 :                             :   VisualEffect::FLAT;
     181             :         aBorder.nBorderColor =   ( nStatus == CONTROL_STATUS_NONE )
     182             :                              ?   _rFallback.nBorderColor
     183           0 :                              :   getControlColorByStatus( nStatus );
     184           0 :         setBorder( _rxPeer, aBorder );
     185           0 :     }
     186             : 
     187             : 
     188           0 :     void ControlBorderManager::determineOriginalBorderStyle( const Reference< XControl >& _rxControl, BorderDescriptor& _rData ) const
     189             :     {
     190           0 :         _rData = ControlData();
     191           0 :         if ( m_aFocusControl.xControl.get() == _rxControl.get() )
     192             :         {
     193           0 :             _rData = m_aFocusControl;
     194             :         }
     195           0 :         else if ( m_aMouseHoverControl.xControl.get() == _rxControl.get() )
     196             :         {
     197           0 :             _rData = m_aMouseHoverControl;
     198             :         }
     199             :         else
     200             :         {
     201           0 :             ControlBag::const_iterator aPos = m_aInvalidControls.find( _rxControl );
     202           0 :             if ( aPos != m_aInvalidControls.end() )
     203             :             {
     204           0 :                 _rData = *aPos;
     205             :             }
     206             :             else
     207             :             {
     208           0 :                 Reference< XVclWindowPeer > xPeer( _rxControl->getPeer(), UNO_QUERY );
     209           0 :                 getBorder( xPeer, _rData );
     210             :             }
     211             :         }
     212           0 :     }
     213             : 
     214             : 
     215           0 :     void ControlBorderManager::controlStatusGained( const Reference< XInterface >& _rxControl, ControlData& _rControlData )
     216             :     {
     217           0 :         if ( _rxControl == _rControlData.xControl )
     218             :             // nothing to do - though suspicious
     219           0 :             return;
     220             : 
     221           0 :         Reference< XControl > xAsControl( _rxControl, UNO_QUERY );
     222             :         DBG_ASSERT( xAsControl.is(), "ControlBorderManager::controlStatusGained: invalid control!" );
     223           0 :         if ( !xAsControl.is() )
     224           0 :             return;
     225             : 
     226             :         try
     227             :         {
     228           0 :             Reference< XVclWindowPeer > xPeer( xAsControl->getPeer(), UNO_QUERY );
     229           0 :             if ( xPeer.is() && canColorBorder( xPeer ) )
     230             :             {
     231             :                 // remember the control and its current border color
     232           0 :                 _rControlData.xControl.clear(); // so determineOriginalBorderStyle doesn't get confused
     233             : 
     234           0 :                 determineOriginalBorderStyle( xAsControl, _rControlData );
     235             : 
     236           0 :                 _rControlData.xControl = xAsControl;
     237             : 
     238           0 :                 updateBorderStyle( xAsControl, xPeer, _rControlData );
     239           0 :             }
     240             :         }
     241           0 :         catch( const Exception& )
     242             :         {
     243             :             OSL_FAIL( "ControlBorderManager::controlStatusGained: caught an exception!" );
     244           0 :         }
     245             :     }
     246             : 
     247             : 
     248           0 :     void ControlBorderManager::controlStatusLost( const Reference< XInterface >& _rxControl, ControlData& _rControlData )
     249             :     {
     250           0 :         if ( _rxControl != _rControlData.xControl )
     251             :             // nothing to do
     252           0 :             return;
     253             : 
     254             :         OSL_PRECOND( _rControlData.xControl.is(), "ControlBorderManager::controlStatusLost: invalid control data - this will crash!" );
     255             :         try
     256             :         {
     257           0 :             Reference< XVclWindowPeer > xPeer( _rControlData.xControl->getPeer(), UNO_QUERY );
     258           0 :             if ( xPeer.is() && canColorBorder( xPeer ) )
     259             :             {
     260           0 :                 ControlData aPreviousStatus( _rControlData );
     261           0 :                 _rControlData = ControlData();
     262           0 :                 updateBorderStyle( aPreviousStatus.xControl, xPeer, aPreviousStatus );
     263           0 :             }
     264             :         }
     265           0 :         catch( const Exception& )
     266             :         {
     267             :             OSL_FAIL( "ControlBorderManager::controlStatusLost: caught an exception!" );
     268             :         }
     269             :     }
     270             : 
     271             : 
     272           0 :     void ControlBorderManager::enableDynamicBorderColor( )
     273             :     {
     274           0 :         m_bDynamicBorderColors = true;
     275           0 :     }
     276             : 
     277             : 
     278          95 :     void ControlBorderManager::disableDynamicBorderColor( )
     279             :     {
     280          95 :         m_bDynamicBorderColors = false;
     281          95 :         restoreAll();
     282          95 :     }
     283             : 
     284             : 
     285           0 :     void ControlBorderManager::setStatusColor( ControlStatus _nStatus, sal_Int32 _nColor )
     286             :     {
     287           0 :         switch ( _nStatus )
     288             :         {
     289             :         case CONTROL_STATUS_FOCUSED:
     290           0 :             m_nFocusColor = _nColor;
     291           0 :             break;
     292             :         case CONTROL_STATUS_MOUSE_HOVER:
     293           0 :             m_nMouseHoveColor = _nColor;
     294           0 :             break;
     295             :         case CONTROL_STATUS_INVALID:
     296           0 :             m_nInvalidColor = _nColor;
     297           0 :             break;
     298             :         default:
     299             :             OSL_FAIL( "ControlBorderManager::setStatusColor: invalid status!" );
     300             :         }
     301           0 :     }
     302             : 
     303             : 
     304         190 :     void ControlBorderManager::restoreAll()
     305             :     {
     306         190 :         if ( m_aFocusControl.xControl.is() )
     307           0 :             controlStatusLost( m_aFocusControl.xControl, m_aFocusControl );
     308         190 :         if ( m_aMouseHoverControl.xControl.is() )
     309           0 :             controlStatusLost( m_aMouseHoverControl.xControl, m_aMouseHoverControl );
     310             : 
     311         190 :         ControlBag aInvalidControls;
     312         190 :         m_aInvalidControls.swap( aInvalidControls );
     313             : 
     314         570 :         for ( ControlBag::const_iterator loop = aInvalidControls.begin();
     315         380 :               loop != aInvalidControls.end();
     316             :               ++loop
     317             :             )
     318             :         {
     319           0 :             Reference< XVclWindowPeer > xPeer( loop->xControl->getPeer(), UNO_QUERY );
     320           0 :             if ( xPeer.is() )
     321             :             {
     322           0 :                 updateBorderStyle( loop->xControl, xPeer, *loop );
     323           0 :                 xPeer->setProperty( FM_PROP_HELPTEXT, makeAny( loop->sOriginalHelpText ) );
     324           0 :                 setUnderline( xPeer, *loop );
     325             :             }
     326         190 :         }
     327         190 :     }
     328             : 
     329             : 
     330           1 :     void ControlBorderManager::focusGained( const Reference< XInterface >& _rxControl )
     331             :     {
     332           1 :         if ( m_bDynamicBorderColors )
     333           0 :             controlStatusGained( _rxControl, m_aFocusControl );
     334           1 :     }
     335             : 
     336             : 
     337           1 :     void ControlBorderManager::focusLost( const Reference< XInterface >& _rxControl )
     338             :     {
     339           1 :         if ( m_bDynamicBorderColors )
     340           0 :             controlStatusLost( _rxControl, m_aFocusControl );
     341           1 :     }
     342             : 
     343             : 
     344           0 :     void ControlBorderManager::mouseEntered( const Reference< XInterface >& _rxControl )
     345             :     {
     346           0 :         if ( m_bDynamicBorderColors )
     347           0 :             controlStatusGained( _rxControl, m_aMouseHoverControl );
     348           0 :     }
     349             : 
     350             : 
     351           0 :     void ControlBorderManager::mouseExited( const Reference< XInterface >& _rxControl )
     352             :     {
     353           0 :         if ( m_bDynamicBorderColors )
     354           0 :             controlStatusLost( _rxControl, m_aMouseHoverControl );
     355           0 :     }
     356             : 
     357             : 
     358          42 :     void ControlBorderManager::validityChanged( const Reference< XControl >& _rxControl, const Reference< XValidatableFormComponent >& _rxValidatable )
     359             :     {
     360             :         try
     361             :         {
     362             :             OSL_ENSURE( _rxControl.is(), "ControlBorderManager::validityChanged: invalid control!" );
     363             :             OSL_ENSURE( _rxValidatable.is(), "ControlBorderManager::validityChanged: invalid validatable!" );
     364             : 
     365          42 :             Reference< XVclWindowPeer > xPeer( _rxControl.is() ? _rxControl->getPeer() : Reference< XWindowPeer >(), UNO_QUERY );
     366          42 :             if ( !xPeer.is() || !_rxValidatable.is() )
     367           0 :                 return;
     368             : 
     369          42 :             ControlData aData( _rxControl );
     370             : 
     371          42 :             if ( _rxValidatable->isValid() )
     372             :             {
     373          42 :                 ControlBag::iterator aPos = m_aInvalidControls.find( aData );
     374          42 :                 if ( aPos != m_aInvalidControls.end() )
     375             :                 {   // invalid before, valid now
     376           0 :                     ControlData aOriginalLayout( *aPos );
     377           0 :                     m_aInvalidControls.erase( aPos );
     378             : 
     379             :                     // restore all the things we used to indicate invalidity
     380           0 :                     if ( m_bDynamicBorderColors )
     381           0 :                         updateBorderStyle( _rxControl, xPeer, aOriginalLayout );
     382           0 :                     xPeer->setProperty( FM_PROP_HELPTEXT, makeAny( aOriginalLayout.sOriginalHelpText ) );
     383           0 :                     setUnderline( xPeer, aOriginalLayout );
     384             :                 }
     385          42 :                 return;
     386             :             }
     387             : 
     388             :             // we're here in the INVALID case
     389           0 :             if ( m_aInvalidControls.find( _rxControl ) == m_aInvalidControls.end() )
     390             :             {   // valid before, invalid now
     391             : 
     392             :                 // remember the current border
     393           0 :                 determineOriginalBorderStyle( _rxControl, aData );
     394             :                 // and tool tip
     395           0 :                 xPeer->getProperty( FM_PROP_HELPTEXT ) >>= aData.sOriginalHelpText;
     396             :                 // and font
     397           0 :                 getUnderline( xPeer, aData );
     398             : 
     399           0 :                 m_aInvalidControls.insert( aData );
     400             : 
     401             :                 // update the border to the new invalidity
     402           0 :                 if ( m_bDynamicBorderColors && canColorBorder( xPeer ) )
     403           0 :                     updateBorderStyle( _rxControl, xPeer, aData );
     404             :                 else
     405             :                 {
     406             :                     // and also the new font
     407           0 :                     setUnderline( xPeer, UnderlineDescriptor( com::sun::star::awt::FontUnderline::WAVE, m_nInvalidColor ) );
     408             :                 }
     409             :             }
     410             : 
     411             :             // update the explanation for invalidity (this is always done, even if the validity did not change)
     412           0 :             Reference< XValidator > xValidator = _rxValidatable->getValidator();
     413             :             OSL_ENSURE( xValidator.is(), "ControlBorderManager::validityChanged: invalid, but no validator?" );
     414           0 :             OUString sExplainInvalidity = xValidator.is() ? xValidator->explainInvalid( _rxValidatable->getCurrentValue() ) : OUString();
     415           0 :             xPeer->setProperty( FM_PROP_HELPTEXT, makeAny( sExplainInvalidity ) );
     416             :         }
     417           0 :         catch( const Exception& )
     418             :         {
     419             :             OSL_FAIL( "ControlBorderManager::validityChanged: caught an exception!" );
     420             :         }
     421             :     }
     422             : 
     423             : 
     424             : }
     425             : 
     426             : 
     427             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11