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

Generated by: LCOV version 1.10