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

Generated by: LCOV version 1.10