/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/XAccessibleValue.hpp>
#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
#include <com/sun/star/accessibility/XAccessibleText.hpp>

#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
#include <memory.h>
#include <algorithm>
#include <assert.h>

#include "AccObject.hxx"
#include "AccEventListener.hxx"
#include "UAccCOM_i.c"
#include "AccResource.hxx"

#include "act.hxx"

using namespace std;
using namespace com::sun::star::uno;
using namespace com::sun::star::accessibility;
using namespace com::sun::star::accessibility::AccessibleRole;
using namespace com::sun::star::accessibility::AccessibleStateType;


/**
   * Constructor.
   * @param pXAcc Uno XAccessible interface of control.
   * @param Agent The agent kept in all listeners,it's the sole interface by which
   *              listener communicate with windows manager.
   * @param listener listener that registers in UNO system.
   * @return.
   */
AccObject::AccObject(XAccessible* pAcc,AccObjectManagerAgent* pAgent ,AccEventListener* listener) :
        m_pIMAcc	(NULL),
        m_resID		(NULL),
        m_pParantID	(NULL),
        m_pParentObj(NULL),
        m_accListener (listener),
        m_bShouldDestroy(sal_False),
        m_xAccRef( pAcc )
{
    sal_Bool bRet = ImplInitilizeCreateObj();

    m_xAccContextRef = m_xAccRef->getAccessibleContext();
    m_xAccActionRef = Reference< XAccessibleAction > (m_xAccContextRef,UNO_QUERY);
    m_accRole = m_xAccContextRef -> getAccessibleRole();
    if( m_pIMAcc )
    {
        m_pIMAcc->SetXAccessible((long) m_xAccRef.get());
        m_pIMAcc->Put_XAccAgent((long)pAgent);
        m_pIMAcc->SetDefaultAction((long)m_xAccActionRef.get());
    }
}
/**
   * Destructor.
   * @param
   * @return
   */
AccObject::~AccObject()
{
    m_pIMAcc = NULL;
    m_xAccRef = NULL;
    m_xAccActionRef = NULL;
    m_xAccContextRef = NULL;
}



/**
   * Insert a child element.
   * @param pChild Child element that should be inserted into child list.
   * @param pos Insert postion.
   * @return
   */
void AccObject::InsertChild( AccObject* pChild,short pos )
{

    std::vector<AccObject*>::iterator iter;
    iter = std::find(m_childrenList.begin(),m_childrenList.end(),pChild);
    if(iter!=m_childrenList.end())
        return;
    if(LAST_CHILD==pos)
    {
        m_childrenList.push_back(pChild);
    }
    else
    {
        std::vector<AccObject*>::iterator iter=m_childrenList.begin()+pos;
        m_childrenList.insert(iter,pChild);
    }

    pChild->SetParentObj(this);
}

/**
   * Delete a child element
   * @param pChild Child element that should be inserted into child list.
   * @param pos Insert postion.
   * @return
   */
void AccObject::DeleteChild( AccObject* pChild )
{
    std::vector<AccObject*>::iterator iter;
    iter = std::find(m_childrenList.begin(),m_childrenList.end(),pChild);
    if(iter!=m_childrenList.end())
    {
        m_childrenList.erase(iter);
        if(m_pIMAcc)
            pChild->SetParentObj(NULL);
    }
}

/**
   * In order to windows API WindowFromAccessibleObject,we sometimes to set a pure
   * top window accessible object created by windows system as top ancestor.
   * @param.
   * @return
   */
void AccObject::UpdateValidWindow()
{
    if(m_pIMAcc)
        m_pIMAcc->Put_XAccWindowHandle(m_pParantID);
}

/**
   * Translate all UNO basic information into MSAA com information.
   * @param
   * @return If the method is correctly processed.
   */
sal_Bool AccObject::ImplInitilizeCreateObj()
{
	ActivateActContext();
	HRESULT hr = CoCreateInstance( CLSID_MAccessible, NULL, CLSCTX_ALL ,
                                   IID_IMAccessible,
                                   (void **)&m_pIMAcc);
	DeactivateActContext();

    if ( S_OK != hr )
    {
        return sal_False;
    }

    return sal_True;
}

/**
   * Update name property to com object.
   * @param
   * @return
   */
void  AccObject::UpdateName( )
{
    if (!m_pIMAcc)
    {
        return;
    }

    if( ( TEXT_FRAME == m_accRole   ) && ( m_pParentObj !=NULL )&& ( SCROLL_PANE == m_pParentObj -> m_accRole ) )
        m_pIMAcc->Put_XAccName( m_pParentObj->m_xAccContextRef->getAccessibleName().getStr() );
    if ( PARAGRAPH == m_accRole)
    {
    	::rtl::OUString emptyStr = ::rtl::OUString::createFromAscii("");
    	m_pIMAcc->Put_XAccName(emptyStr.getStr());
    }
    else
        m_pIMAcc->Put_XAccName(m_xAccContextRef->getAccessibleName().getStr());

    return ;
}
/**
   * Update description property to com object.
   * no content for update description
   * @param
   * @return
   */
void AccObject::UpdateDescription()
{
    if (!m_pIMAcc)
    {
        return;
    }

    m_pIMAcc->Put_XAccDescription(m_xAccContextRef->getAccessibleDescription().getStr());
    return ;
}

/**
   * Update default action property to com object.
   * @param
   * @return
   */
void  AccObject::UpdateAction()
{
    m_xAccActionRef = Reference< XAccessibleAction > (m_xAccContextRef,UNO_QUERY);

    if( m_xAccActionRef.is() && m_pIMAcc )
    {
        if( m_xAccActionRef->getAccessibleActionCount() > 0 )
        {
            UpdateDefaultAction( );
            m_pIMAcc->SetDefaultAction((long)m_xAccActionRef.get());
        }
    }
}

/**
   * Update value property to com object.
   * @param
   * @return
   */
void AccObject::UpdateValue()
{
    if( NULL == m_pIMAcc  || !m_xAccContextRef.is() )
    {
        assert(false);
        return ;
    }

    Reference< XAccessibleValue > pRValue(m_xAccContextRef.get(),UNO_QUERY);
    Any pAny;
    if( pRValue.is() )
    {
        pAny = pRValue->getCurrentValue();
    }

    SetValue( pAny );
}

/**
   * Set special default action description string via UNO role.
   * @param Role UNO role
   * @return
   */
void AccObject::UpdateDefaultAction( )
{
    if(!m_xAccActionRef.is())
        return ;

    switch(m_accRole)
    {
    case PUSH_BUTTON:
    case TOGGLE_BUTTON:
    case RADIO_BUTTON:
    case MENU_ITEM:
    case RADIO_MENU_ITEM:
    case CHECK_MENU_ITEM:
    case LIST_ITEM:
    case CHECK_BOX:
    case TREE_ITEM:
    case BUTTON_DROPDOWN:
        m_pIMAcc->Put_ActionDescription( m_xAccActionRef->getAccessibleActionDescription((sal_Int32)0).getStr() );
        return;
    }
}

/**
   * Set value property via pAny.
   * @param pAny New value.
   * @return
   */
void  AccObject::SetValue( Any pAny )
{
    unsigned short pUNumberString[100];
    memset( pUNumberString, 0 , sizeof( pUNumberString) );

    if( NULL == m_pIMAcc || !m_xAccContextRef.is() )
    {
        assert(false);
        return ;
    }
    Reference< XAccessibleText > pRText(m_xAccContextRef,UNO_QUERY);
    ::rtl::OUString val;
    int index = 0 ;
    switch(m_accRole)
    {
    case SPIN_BOX:
        // 3. date editor's msaa value should be the same as spinbox
    case DATE_EDITOR:
    case TEXT:
    case PARAGRAPH:
    case HEADING:

        if(pRText.get())
        {
            val = pRText->getText();
        }
        m_pIMAcc->Put_XAccValue( val.getStr() );
        break;
    case TREE_ITEM:
    //case CHECK_BOX:	//Commented by Li Xing to disable the value for general checkbox
    case COMBO_BOX:
    case TABLE_CELL:
    case NOTE:
    case SCROLL_BAR:
        m_pIMAcc->Put_XAccValue( GetMAccessibleValueFromAny(pAny).getStr() );
        break ;
	// Added by Li Xing, only the checkbox in tree should have the value. 
	case CHECK_BOX:
		if( ( m_pParentObj !=NULL ) && (TREE == m_pParentObj->m_accRole || TREE_ITEM == m_pParentObj->m_accRole ))
	        m_pIMAcc->Put_XAccValue( GetMAccessibleValueFromAny(pAny).getStr() );
		break;
    default:
        break;
    }

    return;


}
::rtl::OUString AccObject::GetMAccessibleValueFromAny(Any pAny)
{
    ::rtl::OUString strValue;

    if(NULL == m_pIMAcc)
        return strValue;

    if(pAny.getValueType() == getCppuType( (sal_uInt16 *)0 ) )
    {
        sal_uInt16 val;
        if (pAny >>= val)
        {
            strValue=::rtl::OUString::valueOf((sal_Int32)val);

        }
    }
    else if(pAny.getValueType() == getCppuType( (::rtl::OUString *)0 ) )
    {

        pAny >>= strValue ;

    }
    else if(pAny.getValueType() == getCppuType( (Sequence< ::rtl::OUString > *)0 ) )
    {
        Sequence< ::rtl::OUString > val;
        if (pAny >>= val)
        {

            int count = val.getLength();

            for( int iIndex = 0;iIndex < count;iIndex++ )
            {
                strValue += val[iIndex];
            }

        }
    }
    else if(pAny.getValueType() == getCppuType( (double *)0 ) )
    {
        double val;
        if (pAny >>= val)
        {
            strValue=::rtl::OUString::valueOf(val);
        }
    }
    else if(pAny.getValueType() == getCppuType( (sal_Int32 *)0 ) )
    {
        sal_Int32 val;
        if (pAny >>= val)
        {
            strValue=::rtl::OUString::valueOf(val);
        }
    }
    else if (pAny.getValueType() == getCppuType( (com::sun::star::accessibility::TextSegment *)0 ) )
    {
        com::sun::star::accessibility::TextSegment val;
        if (pAny >>= val)
        {
            ::rtl::OUString realVal(val.SegmentText);
            strValue = realVal;

        }
    }

    return strValue;
}
/**
   * Set name property via pAny.
   * @param pAny New accessible name.
   * @return
   */
void  AccObject::SetName( Any pAny)
{
    if( NULL == m_pIMAcc )
        return ;

    m_pIMAcc->Put_XAccName( GetMAccessibleValueFromAny(pAny).getStr() );

}

/**
   * Set description property via pAny.
   * @param pAny New accessible description.
   * @return
   */
void  AccObject::SetDescription( Any pAny )
{
    if( NULL == m_pIMAcc )
        return ;
    m_pIMAcc->Put_XAccDescription( GetMAccessibleValueFromAny(pAny).getStr() );
}

/**
   * Set role property via pAny
   * @param Role New accessible role.
   * @return
   */
void  AccObject::SetRole( short Role )
{
    if( NULL == m_pIMAcc )
        return ;
    m_pIMAcc->Put_XAccRole( Role );
}

/**
* Get role property via pAny
* @param
* @return accessible role
*/
short AccObject::GetRole() const
{
    return m_accRole;
}

/**
   * Get MSAA state from UNO state
   * @Role xState UNO state.
   * @return
   */
DWORD AccObject::GetMSAAStateFromUNO(short xState)
{
    DWORD IState = UNO_MSAA_UNMAPPING;

    if( !m_xAccContextRef.is() )
    {
        assert(false);
        return IState;
    }
    short Role = m_accRole;

    switch( xState )
    {
    case  BUSY:
        IState = STATE_SYSTEM_BUSY;
        break;
    case  CHECKED:
        if( Role == PUSH_BUTTON || Role == TOGGLE_BUTTON )
        {
            IState = STATE_SYSTEM_PRESSED;
        }
        else
            IState = STATE_SYSTEM_CHECKED;
        break;
    case  DEFUNC:
        IState = STATE_SYSTEM_UNAVAILABLE;
        break;
    case  EXPANDED:
        IState = STATE_SYSTEM_EXPANDED;
        break;
    case  FOCUSABLE:
        IState = STATE_SYSTEM_FOCUSABLE;
        break;
    case  FOCUSED:
        IState = STATE_SYSTEM_FOCUSED;
        break;
    case  INDETERMINATE:
        IState = STATE_SYSTEM_MIXED;
        break;
    case  MULTI_SELECTABLE:
        IState = STATE_SYSTEM_MULTISELECTABLE;
        break;
    case  PRESSED:
        IState = STATE_SYSTEM_PRESSED;
        break;
    case  RESIZABLE:
        IState = STATE_SYSTEM_SIZEABLE;
        break;
    case  SELECTABLE:
        if( m_accRole == MENU || m_accRole == MENU_ITEM)
        {
            IState = UNO_MSAA_UNMAPPING;
        }
        else
        {
            IState = STATE_SYSTEM_SELECTABLE;
        }
        break;
    case  SELECTED:
        if( m_accRole == MENU || m_accRole == MENU_ITEM )
        {
            IState = UNO_MSAA_UNMAPPING;
        }
        else
        {
            IState = STATE_SYSTEM_SELECTED;
        }
        break;
    case  ARMED:
        IState = STATE_SYSTEM_FOCUSED;
        break;
    case  EXPANDABLE:
        {
            sal_Bool isExpanded = sal_True;
            sal_Bool isExpandable = sal_True;
            if( Role == PUSH_BUTTON || Role == TOGGLE_BUTTON  || BUTTON_DROPDOWN == Role )
            {
                IState = STATE_SYSTEM_HASPOPUP;
            }
            else
            {
                GetExpandedState(&isExpandable,&isExpanded);
                if(!isExpanded)
                    IState = STATE_SYSTEM_COLLAPSED;
            }
        }
        break;
	//Remove the SENSITIVE state mapping. There is no corresponding MSAA state. 
    //case  SENSITIVE:
    //    IState = STATE_SYSTEM_PROTECTED;
    case EDITABLE:
        if( m_pIMAcc )
        {
            m_pIMAcc->DecreaseState( STATE_SYSTEM_READONLY );
        }
        break;
    case OFFSCREEN:
        IState = STATE_SYSTEM_OFFSCREEN;
        break;
    case MOVEABLE:
        IState = STATE_SYSTEM_MOVEABLE;
        break;
    case COLLAPSE:
        IState = STATE_SYSTEM_COLLAPSED;
        break;
    case DEFAULT:
        IState = STATE_SYSTEM_DEFAULT;
        break;
    default:
        break;
    }

    return IState;
}

/**
   * Decrease state of com object
   * @param xState The lost state.
   * @return
   */
void  AccObject::DecreaseState( short xState )
{
    if( NULL == m_pIMAcc )
    {
        return;
    }

    if( xState == FOCUSABLE)
    {
        short Role = m_accRole ;
        if(Role == MENU_ITEM
                || Role == RADIO_MENU_ITEM
                || Role == CHECK_MENU_ITEM)
            return;
        else
        {
            if (Role == TOGGLE_BUTTON || Role == PUSH_BUTTON || BUTTON_DROPDOWN == Role)
            {
                if( ( m_pParentObj !=NULL ) && (TOOL_BAR == m_pParentObj->m_accRole ) )
                    return;
            }
        }
    }

    else if( xState == AccessibleStateType::VISIBLE  )
    {
        m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE );
    }
    else if( xState == AccessibleStateType::SHOWING )
    {
        m_pIMAcc->IncreaseState( STATE_SYSTEM_OFFSCREEN );
    }

    DWORD msState = GetMSAAStateFromUNO(xState);
    if(msState!=UNO_MSAA_UNMAPPING)
        m_pIMAcc->DecreaseState(msState);
}

/**
   * Increase state of com object
   * @param xState The new state.
   * @return
   */
void AccObject::IncreaseState( short xState )
{
    if( NULL == m_pIMAcc )
    {
        assert(false);
        return;
    }


    if( xState == AccessibleStateType::VISIBLE  )
    {
        m_pIMAcc->DecreaseState( STATE_SYSTEM_INVISIBLE );
    }
    else if( xState == AccessibleStateType::SHOWING )
    {
        m_pIMAcc->DecreaseState( STATE_SYSTEM_OFFSCREEN );
    }


    DWORD msState = GetMSAAStateFromUNO(xState);
    if(msState!=UNO_MSAA_UNMAPPING)
        m_pIMAcc->IncreaseState( msState );
}

/**
   * Get next child element
   * @param
   * @return AccObject Object interface.
   */
AccObject* AccObject::NextChild()
{
    IAccChildList::iterator pInd = m_childrenList.begin();
    if( pInd != m_childrenList.end() )
        return 	*pInd;
    return NULL;
}
/**
   * update action desciption desc
   * @param
   * @return 
   */
void AccObject::UpdateActionDesc()
{
    if (!m_pIMAcc)
    {
        return;
    }

    ::rtl::OUString	pXString = m_xAccContextRef->getAccessibleDescription();
    m_pIMAcc->Put_XAccDescription(pXString.getStr());
    long Role = m_accRole;

    if(  Role == PUSH_BUTTON || Role == RADIO_BUTTON || Role == MENU_ITEM ||
            Role == LIST_ITEM || Role == CHECK_BOX || Role == TREE_ITEM ||
            Role == CHECK_MENU_ITEM || Role == RADIO_MENU_ITEM )
    {
        UpdateDefaultAction(  );
    }
    else
    {

        if( m_xAccActionRef.is() )
        {
            if( m_xAccActionRef->getAccessibleActionCount() > 0 )
            {
				if (!(Role == SPIN_BOX || Role == COMBO_BOX || Role == DATE_EDITOR ||
					  Role == EDIT_BAR || Role == PASSWORD_TEXT || Role == TEXT))
				{
					pXString = m_xAccActionRef->getAccessibleActionDescription( 0 );
					//Solution:If string length is more than zero,action will will be set.
					if( pXString.getLength() > 0)
						m_pIMAcc->Put_ActionDescription( pXString.getStr() );
				}                
            }
        }
    }

}
/**
   * update role information from uno to com
   * @param
   * @return 
   */
void AccObject::UpdateRole()
{
    if (!m_pIMAcc)
    {
        return;
    }

    XAccessibleContext* pContext  = m_xAccContextRef.get();
    m_pIMAcc->Put_XAccRole( ROLE_SYSTEM_WINDOW  );
    short iRoleIndex = pContext->getAccessibleRole();
    if (( 0 <= iRoleIndex) && ( iRoleIndex <= (sizeof(ROLE_TABLE)/(sizeof(short)*2))))
    {
        short iIA2Role = ROLE_TABLE[iRoleIndex][1] ;
        m_pIMAcc->Put_XAccRole( iIA2Role  );
    }

}
/**
   * update state information from uno to com
   * @param
   * @return 
   */
void AccObject::UpdateState()
{
    if (!m_pIMAcc)
    {
        return;
    }

    XAccessibleContext* pContext  = m_xAccContextRef.get();
    Reference< XAccessibleStateSet > pRState = pContext->getAccessibleStateSet();
    if( !pRState.is() )
    {
        assert(false);
        return ;
    }

    m_pIMAcc->SetState(0L);

    if ( m_accRole == POPUP_MENU )
    {
        return;
    }

    Sequence<short> pStates = pRState->getStates();
    int count = pStates.getLength();

    sal_Bool isEnable = sal_False;
    sal_Bool isShowing = sal_False;
    sal_Bool isEditable = sal_False;
    sal_Bool isVisible = sal_False;
    sal_Bool isFocusable = sal_False;

    for( int iIndex = 0;iIndex < count;iIndex++ )
    {
        if( pStates[iIndex] == ENABLED )
            isEnable = sal_True;
        else if( pStates[iIndex] == SHOWING)
            isShowing = sal_True;
        else if( pStates[iIndex] == VISIBLE)
            isVisible = sal_True;
        else if( pStates[iIndex] == EDITABLE )
            isEditable = sal_True;
        else if (pStates[iIndex] == FOCUSABLE)
            isFocusable = sal_True;
        IncreaseState( pStates[iIndex]);
    }
    sal_Bool bIsMenuItem = m_accRole == MENU_ITEM || m_accRole == RADIO_MENU_ITEM || m_accRole == CHECK_MENU_ITEM;

    if(bIsMenuItem)
    {
        if(!(isShowing && isVisible) )
        {
            m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE );
            m_pIMAcc->DecreaseState( STATE_SYSTEM_FOCUSABLE );
        }
    }
    else
    {
        if(!(isShowing || isVisible) )
            m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE );
    }

    short Role = m_accRole;

    if( m_pIMAcc )
    {
        switch(m_accRole)
        {
        case LABEL:
            m_pIMAcc->IncreaseState( STATE_SYSTEM_READONLY );
            break;
        case TEXT:
            // 2. editable combobox -> readonly ------ bridge
        case EMBEDDED_OBJECT:
        case END_NOTE:
        case FOOTER:
        case FOOTNOTE:
        case GRAPHIC:
        case HEADER:
        case HEADING:

            //Image Map
        case PARAGRAPH:
        case PASSWORD_TEXT:
        case SHAPE:
        case SPIN_BOX:
        case TABLE:
        case TABLE_CELL:
        case TEXT_FRAME:
        case DATE_EDITOR:
        case DOCUMENT:
        case COLUMN_HEADER:
            {
                if(!isEditable)
                    m_pIMAcc->IncreaseState( STATE_SYSTEM_READONLY );
            }
            break;
        default:
            break;
        }
    }

    if( isEnable )
    {

        if(!(Role == FILLER || Role == END_NOTE || Role == FOOTER || Role == FOOTNOTE || Role == GROUP_BOX || Role == RULER
                || Role == HEADER || Role == ICON || Role == INTERNAL_FRAME || Role == LABEL || Role == LAYERED_PANE
                || Role == SCROLL_BAR || Role == SCROLL_PANE || Role == SPLIT_PANE || Role == STATUS_BAR || Role == TOOL_TIP))
        {
            if( SEPARATOR == Role  )
            {
                if( ( m_pParentObj != NULL ) && ( MENU == m_pParentObj->m_accRole  || POPUP_MENU == m_pParentObj->m_accRole ))
                    IncreaseState( FOCUSABLE );
            }

            else if (TABLE_CELL == Role || TABLE == Role || PANEL == Role || OPTION_PANE == Role ||
                     COLUMN_HEADER == Role)
            {
                if (isFocusable)
                    IncreaseState( FOCUSABLE );
            }
            else
            {
                if(bIsMenuItem)
                {
                    if ( isShowing && isVisible)
                    {
                        IncreaseState( FOCUSABLE );
                    }
                }
                else
                {
                    IncreaseState( FOCUSABLE );
                }
            }
        }
    }
    else
    {
        m_pIMAcc->IncreaseState( STATE_SYSTEM_UNAVAILABLE );
        sal_Bool isDecreaseFocusable = sal_False;
        if( !((Role == MENU_ITEM) ||
                (Role == RADIO_MENU_ITEM) ||
                (Role == CHECK_MENU_ITEM)) )
        {
            if  ( Role == TOGGLE_BUTTON || Role == PUSH_BUTTON || BUTTON_DROPDOWN == Role)
            {
                if(( m_pParentObj != NULL )&& (TOOL_BAR ==  m_pParentObj->m_accRole ) )
                    IncreaseState( FOCUSABLE );
                else
                    DecreaseState( FOCUSABLE );
            }
            else
                DecreaseState( FOCUSABLE );
        }
        else if( isShowing || isVisible )
        {
            IncreaseState( FOCUSABLE );
        }
    }

    if( m_pIMAcc )
    {
        switch(m_accRole)
        {
        case POPUP_MENU:
        case MENU:
            if( pContext->getAccessibleChildCount() > 0 )
                m_pIMAcc->IncreaseState( STATE_SYSTEM_HASPOPUP );
            break;
        case PASSWORD_TEXT:
            m_pIMAcc->IncreaseState( STATE_SYSTEM_PROTECTED );
            break;
        default:
            break;
        }
    }

}
/**
   * update location information from uno to com
   * @param
   * @return 
   */
void AccObject::UpdateLocation()
{
    if (!m_pIMAcc)
    {
        return;
    }
    XAccessibleContext* pContext  = m_xAccContextRef.get();

    Reference< XAccessibleComponent > pRComponent(pContext,UNO_QUERY);
    if( pRComponent.is() )
    {
        ::com::sun::star::awt::Point pCPoint = pRComponent->getLocationOnScreen();
        ::com::sun::star::awt::Size pCSize = pRComponent->getSize();
        Location tempLocation;
        tempLocation.m_dLeft = pCPoint.X;
        tempLocation.m_dTop =  pCPoint.Y;
        tempLocation.m_dWidth = pCSize.Width;
        tempLocation.m_dHeight = pCSize.Height;
        m_pIMAcc->Put_XAccLocation( tempLocation );
    }

}


/**
   * Public method to mapping information between MSAA and UNO.
   * @param
   * @return If the method is correctly processed.
   */
sal_Bool AccObject:: UpdateAccessibleInfoFromUnoToMSAA ( )
{
    if( NULL == m_pIMAcc || !m_xAccContextRef.is()  )
    {
        assert(false);
        return sal_False;
    }

    UpdateName();

    UpdateValue();

    UpdateActionDesc();

    UpdateRole();

    UpdateLocation();

    UpdateState();

    return sal_True;
}

/*
   * Add a child selected element.
   * @param pAccObj Child object pointer.
   * @return
   */
void AccObject::AddSelect( long index, AccObject* accObj)
{
    m_selectionList.insert(IAccSelectionList::value_type(index,accObj));
}

IAccSelectionList& AccObject::GetSelection()
{
    return m_selectionList;
}


/**
   * Set self to focus object in parant child list
   * @param
   * @return
   */
void AccObject::setFocus()
{
    if(m_pIMAcc)
    {
        IncreaseState(FOCUSED);
        m_pIMAcc->Put_XAccFocus(CHILDID_SELF);

        UpdateRole();
    }
}

/**
   * Unset self from focus object in parant child list.
   * @param
   * @return
   */
void AccObject::unsetFocus()
{
    if(m_pIMAcc)
    {
        DecreaseState( FOCUSED );
        m_pIMAcc->Put_XAccFocus(UACC_NO_FOCUS);
    }
}

void AccObject::GetExpandedState( sal_Bool* isExpandable, sal_Bool* isExpanded)
{
    *isExpanded = sal_False;
    *isExpandable = sal_False;

    if( !m_xAccContextRef.is() )
    {
        return;
    }
    Reference< XAccessibleStateSet > pRState = m_xAccContextRef->getAccessibleStateSet();
    if( !pRState.is() )
    {
        return;
    }

    Sequence<short> pStates = pRState->getStates();
    int count = pStates.getLength();

    for( int iIndex = 0;iIndex < count;iIndex++ )
    {
        if( EXPANDED == pStates[iIndex]  )
        {
            *isExpanded = sal_True;
        }
        else if( EXPANDABLE == pStates[iIndex]  )
        {
            *isExpandable = sal_True;
        }
    }
}

void AccObject::NotifyDestroy(sal_Bool ifDelete)
{
    m_bShouldDestroy=ifDelete;
    if(m_pIMAcc)
        m_pIMAcc->NotifyDestroy(m_bShouldDestroy);
}

void AccObject::SetParentObj(AccObject* pParentAccObj)
{
    m_pParentObj = pParentAccObj;

    if(m_pIMAcc)
    {
        if(m_pParentObj)
        {
            m_pIMAcc->Put_XAccParent(m_pParentObj->GetIMAccessible());
        }
        else
        {
            m_pIMAcc->Put_XAccParent(NULL);
        }
    }
}
//ResID means ChildID in MSAA
void AccObject::SetResID(long id)
{
    m_resID = id;
    if(m_pIMAcc)
        m_pIMAcc->Put_XAccChildID(m_resID);
}
//return COM interface in acc object
IMAccessible*  AccObject::GetIMAccessible()
{
    return m_pIMAcc;
}

Reference < XAccessible > AccObject::GetXAccessible()
{
    return m_xAccRef;
}

void AccObject::SetParentHWND(HWND hWnd)
{
    m_pParantID = hWnd;
}
void AccObject::SetListener( AccEventListener* Listener )
{
    m_accListener = Listener;
}
AccEventListener* AccObject::getListener()
{
    return m_accListener;
}

long AccObject::GetResID()
{
    return m_resID;
}

HWND AccObject::GetParentHWND()
{
    return m_pParantID;
}

AccObject* AccObject::GetParentObj()
{
    return m_pParentObj;
}
sal_Bool  AccObject::ifShouldDestroy()
{
    return m_bShouldDestroy;
}
