<commit_before>// Copyright (c) 2017 Leander Perera
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#pragma once

/// The dynarray class manages an automatically re-sizing collection of elements.
template <class T>
class dynarray
{
public:
  dynarray(unsigned int size = 0);
  ~dynarray();
  T get_element(unsigned int index);
  bool set_element(unsigned int index, T element);
  bool insert_element(unsigned int index, T element);
  bool delete_element(unsigned int index);
  unsigned int array_capacity();
  bool is_empty();
private:
  bool resize_array(int newsize);
  T *mp_array;
  unsigned int m_capacity;	  // Size allocated for the array
};

/// Function Swaps the values of the first and second arguments passed
///
/// @param[in,out] first reference to first item to swap
/// @param[in,out] second reference to second item to swap
template <class T>
void swap(T &first, T &second)
{
  T temp = first;
  first = second;
  second = temp;
}

/// Function that copies the specified range of elements from the source array to the destination array
///
/// @param[in,out] dest_array The destination array to which elements will be copied to
/// @param[in] src_array The source array to which elements will be copied from
/// @param[in] from_index The starting index for the copy
/// @param[in] to_index The ending index for the copy
template <class T>
bool copy_array_range(T &dest_array, const T &src_array, unsigned int from_index, unsigned int to_index)
{
  return false;
}

/// Resize the array by the specified size.
///
/// The function creates a new array of the specified size and copies the
/// contents from the old array to the new array. The old array is deallocated.
/// The function also updates the size of the dynamic array to the new size.
/// The newsize needs to be larger than the currently allocated size of the
/// array.
///
/// @param[in] newsize the size of the reallocated array
/// @return    true if successful, false otherwise
template <class T>
bool dynarray<T>::resize_array(int newsize)
{
  bool retval = false;

  // Only resize if new size is larger than the currently allocated capacity
  if (newsize > m_capacity) {
    // Allocate new array of specified capacity
    T *p_new_array = new T[newsize]{}; // Initialize the elements to 0s
    if (p_new_array) {
      // Copy over elements from old array to new array
      for (unsigned int i = 0; i < m_capacity; ++i) {
        p_new_array[i] = mp_array[i];
      }

      // De-allocate the old array and make it point to the new array
      delete []mp_array;
      mp_array = p_new_array;

      // Update the new size of the array
      m_capacity = newsize;
      retval = true;
    }
  }

  return retval;
}

/// Constructor with initial size for the dynamic array.
///
/// @param[in] size Amount of space to allocate for the dynamic array.
///                 By default a 0 size array is created if no arguments
///                 are specified.
template <class T>
dynarray<T>::dynarray(unsigned int size)
{
  // Initialize array elements to 0s. Ensure that allocation
  //  does not throw an exception, but rather returns a NULL on failure.
  mp_array = new (std::nothrow) T[size]{};
  m_capacity = 0;

  // Set the size if the allocation was successful
  if (mp_array) {
      m_capacity = size;
  }
}

/// Destructor deallocates memory allocated for the dynamic array
template <class T>
dynarray<T>::~dynarray()
{
  delete[] mp_array;
  mp_array = NULL;
}

/// Returns the element at the specified index
///
/// @param[in] index A zero-based index ranging from from 0 to the size
//                   of the array - 1.
template <class T>
T dynarray<T>::get_element(unsigned int index)
{
	T retVal;
	if (mp_array && index < m_capacity) {
		retVal = mp_array[index];
	}

  return retVal;
}

/// Sets the element at the specified index.
///
/// The index needs to be within the capacity of the array. If not the function
/// will return a failure code.
///
/// @param[in] index A zero-based index ranging from from 0 to the size
///                  of the array - 1.
/// @param[in] element The element to be stored at the specified index
/// @return true if successful, false otherwise
template <class T>
bool dynarray<T>::set_element(unsigned int index, T element)
{
  bool retval = false;
  if (mp_array && index < m_capacity) {
    // Store the element at the index
    mp_array[index] = element;
    retval = true;
  }

  return retval;
}

/// Insert the specified element at the specified index.
///
/// @param[in] index A zero-based index ranging from from 0 to the size
///                  of the array. If the index is equal to the size of the
///                  dynamic array, the element is added to the end of the
///                  dynamic array.
/// @param[in] element The item to be inserted into the dynamic array.
template <class T>
bool dynarray<T>::insert_element(unsigned int index, T element)
{
  bool retval = false;

  // The index needs to be between 0 and the capacity (inclusive)
  // If inserting new element at the begining, index is 0.
  // If inserting new element at the end, index = capacity.
  if (index <= m_capacity) {
    // Allocate array large enough to hold new element.
    // Initialize each element to 0.
    T *new_array = new T[m_capacity + 1]{};

    if (new_array) {
      // Store the new element at the index
      new_array[index] = element;

      // Copy the rest of the items to the new_array
      for (int i = 0, j = 0; i < m_capacity; ++i, ++j) {
        if (i == index) {
          // Skip the index for the new element that was already stored
          ++j;
        }
        new_array[j] = mp_array[i];
      }

      // Deallocate old array
      delete[] mp_array;

      // Assign new array
      mp_array = new_array;

      // Update the capacity of the array
      m_capacity += 1;
      retval = true;
    }
  }

	return retval;
}

/// Delete the element at the specified index.
///
/// @param[in] index A zero-based index ranging from from 0 to the size
///                  of the array - 1.
template <class T>
bool dynarray<T>::delete_element(unsigned int index)
{
  return false;
}

/// Returns the capacity of the backing array
/// @return capacity of backing array
template <class T>
unsigned int dynarray<T>::array_capacity()
{
  return m_capacity;
}

/// Returns whether or not the array is empty
/// @return TRUE - array is empty, FALSE otherwise
template <class T>
bool dynarray<T>::is_empty()
{
  return (m_capacity == 0);
}
<commit_msg>Used size_t instead of unsigned int to take advantage of 64bit systems that can address more memory.<commit_after>// Copyright (c) 2017 Leander Perera
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#pragma once
#include <cstdlib>

/// The dynarray class manages an automatically re-sizing collection of elements.
template <class T>
class dynarray
{
public:
  dynarray(size_t size = 0);
  ~dynarray();
  T get_element(size_t index);
  bool set_element(size_t index, T element);
  bool insert_element(size_t index, T element);
  bool delete_element(size_t index);
  size_t array_capacity();
  bool is_empty();
private:
  bool resize_array(size_t newsize);
  T *mp_array;
  size_t m_capacity;	  // Size allocated for the array
};

/// Function Swaps the values of the first and second arguments passed
///
/// @param[in,out] first reference to first item to swap
/// @param[in,out] second reference to second item to swap
template <class T>
void swap(T &first, T &second)
{
  T temp = first;
  first = second;
  second = temp;
}

/// Function that copies the specified range of elements from the source array to the destination array
///
/// @param[in,out] dest_array The destination array to which elements will be copied to
/// @param[in] src_array The source array to which elements will be copied from
/// @param[in] from_index The starting index for the copy
/// @param[in] to_index The ending index for the copy
template <class T>
bool copy_array_range(T &dest_array, const T &src_array, size_t from_index, size_t to_index)
{
  return false;
}

/// Resize the array by the specified size.
///
/// The function creates a new array of the specified size and copies the
/// contents from the old array to the new array. The old array is deallocated.
/// The function also updates the size of the dynamic array to the new size.
/// The newsize needs to be larger than the currently allocated size of the
/// array.
///
/// @param[in] newsize the size of the reallocated array
/// @return    true if successful, false otherwise
template <class T>
bool dynarray<T>::resize_array(size_t newsize)
{
  bool retval = false;

  // Only resize if new size is larger than the currently allocated capacity
  if (newsize > m_capacity) {
    // Allocate new array of specified capacity
    T *p_new_array = new T[newsize]{}; // Initialize the elements to 0s
    if (p_new_array) {
      // Copy over elements from old array to new array
      for (unsigned int i = 0; i < m_capacity; ++i) {
        p_new_array[i] = mp_array[i];
      }

      // De-allocate the old array and make it point to the new array
      delete []mp_array;
      mp_array = p_new_array;

      // Update the new size of the array
      m_capacity = newsize;
      retval = true;
    }
  }

  return retval;
}

/// Constructor with initial size for the dynamic array.
///
/// @param[in] size Amount of space to allocate for the dynamic array.
///                 By default a 0 size array is created if no arguments
///                 are specified.
template <class T>
dynarray<T>::dynarray(size_t size)
{
  // Initialize array elements to 0s. Ensure that allocation
  //  does not throw an exception, but rather returns a NULL on failure.
  mp_array = new (std::nothrow) T[size]{};
  m_capacity = 0;

  // Set the size if the allocation was successful
  if (mp_array) {
      m_capacity = size;
  }
}

/// Destructor deallocates memory allocated for the dynamic array
template <class T>
dynarray<T>::~dynarray()
{
  delete[] mp_array;
  mp_array = NULL;
}

/// Returns the element at the specified index
///
/// @param[in] index A zero-based index ranging from from 0 to the size
//                   of the array - 1.
template <class T>
T dynarray<T>::get_element(size_t index)
{
	T retVal;
	if (mp_array && index < m_capacity) {
		retVal = mp_array[index];
	}

  return retVal;
}

/// Sets the element at the specified index.
///
/// The index needs to be within the capacity of the array. If not the function
/// will return a failure code.
///
/// @param[in] index A zero-based index ranging from from 0 to the size
///                  of the array - 1.
/// @param[in] element The element to be stored at the specified index
/// @return true if successful, false otherwise
template <class T>
bool dynarray<T>::set_element(size_t index, T element)
{
  bool retval = false;
  if (mp_array && index < m_capacity) {
    // Store the element at the index
    mp_array[index] = element;
    retval = true;
  }

  return retval;
}

/// Insert the specified element at the specified index.
///
/// @param[in] index A zero-based index ranging from from 0 to the size
///                  of the array. If the index is equal to the size of the
///                  dynamic array, the element is added to the end of the
///                  dynamic array.
/// @param[in] element The item to be inserted into the dynamic array.
template <class T>
bool dynarray<T>::insert_element(size_t index, T element)
{
  bool retval = false;

  // The index needs to be between 0 and the capacity (inclusive)
  // If inserting new element at the begining, index is 0.
  // If inserting new element at the end, index = capacity.
  if (index <= m_capacity) {
    // Allocate array large enough to hold new element.
    // Initialize each element to 0.
    T *new_array = new T[m_capacity + 1]{};

    if (new_array) {
      // Store the new element at the index
      new_array[index] = element;

      // Copy the rest of the items to the new_array
      for (int i = 0, j = 0; i < m_capacity; ++i, ++j) {
        if (i == index) {
          // Skip the index for the new element that was already stored
          ++j;
        }
        new_array[j] = mp_array[i];
      }

      // Deallocate old array
      delete[] mp_array;

      // Assign new array
      mp_array = new_array;

      // Update the capacity of the array
      m_capacity += 1;
      retval = true;
    }
  }

	return retval;
}

/// Delete the element at the specified index.
///
/// @param[in] index A zero-based index ranging from from 0 to the size
///                  of the array - 1.
template <class T>
bool dynarray<T>::delete_element(size_t index)
{
  return false;
}

/// Returns the capacity of the backing array
/// @return capacity of backing array
template <class T>
size_t dynarray<T>::array_capacity()
{
  return m_capacity;
}

/// Returns whether or not the array is empty
/// @return TRUE - array is empty, FALSE otherwise
template <class T>
bool dynarray<T>::is_empty()
{
  return (m_capacity == 0);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserlistbox.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: vg $ $Date: 2006-03-14 11:17:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_
#define _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERLINE_HXX_
#include "browserline.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_PCRCOMMON_HXX_
#include "pcrcommon.hxx"
#endif

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_INSPECTION_XPROPERTYCONTROL_HPP_
#include <com/sun/star/inspection/XPropertyControl.hpp>
#endif
#ifndef _COM_SUN_STAR_INSPECTION_XPROPERTYHANDLER_HPP_
#include <com/sun/star/inspection/XPropertyHandler.hpp>
#endif
/** === end UNO includes === **/

#ifndef _SV_SCRBAR_HXX
#include <vcl/scrbar.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#include <set>
#include <vector>
#include <hash_map>
#include <boost/shared_ptr.hpp>

//............................................................................
namespace pcr
{
//............................................................................

    class IPropertyLineListener;
    struct OLineDescriptor;
    class PropertyControlContext_Impl;

    //========================================================================
    //= administrative structures for OBrowserListBox
    //========================================================================
    typedef ::boost::shared_ptr< OBrowserLine > BrowserLinePointer;
    struct ListBoxLine
    {
        BrowserLinePointer                      pLine;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyHandler >
                                                xHandler;

        ListBoxLine() { }
        ListBoxLine( BrowserLinePointer _pLine, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyHandler >& _rxHandler )
            :pLine( _pLine )
            ,xHandler( _rxHandler )
        {
        }
    };
    typedef ::std::hash_map< ::rtl::OUString, ListBoxLine, ::rtl::OUStringHash >    ListBoxLines;
    typedef ::std::vector< ListBoxLines::iterator >                                 OrderedListBoxLines;

    //========================================================================
    //= IControlContext
    //========================================================================
    /** non-UNO version of XPropertyControlContext
    */
    class SAL_NO_VTABLE IControlContext
    {
    public:
        virtual void SAL_CALL focusGained( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException) = 0;
        virtual void SAL_CALL controlValueChanged( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException) = 0;
        virtual void SAL_CALL activateNextControl( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& CurrentControl ) throw (::com::sun::star::uno::RuntimeException) = 0;
    };

    //========================================================================
    //= OBrowserListBox
    //========================================================================
    class OBrowserListBox   :public Control
                            ,public IButtonClickListener
                            ,public IControlContext
                            ,public PcrClient
    {
    protected:
        Window                      m_aPlayGround;
        ScrollBar                   m_aVScroll;
        ListBoxLines                m_aLines;
        OrderedListBoxLines         m_aOrderedLines;
        IPropertyLineListener*      m_pLineListener;
        long                        m_nYOffset;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >
                                    m_xActiveControl;
        sal_uInt16                  m_nTheNameSize;
        sal_uInt16                  m_nRowHeight;
        ::std::set< sal_uInt16 >    m_aOutOfDateLines;
        sal_Bool                    m_bIsActive : 1;
        sal_Bool                    m_bUpdate : 1;
        ::rtl::Reference< PropertyControlContext_Impl >
                                    m_pControlContextImpl;

    protected:
        void    PositionLine( sal_uInt16 _nIndex );
        void    UpdatePosNSize();
        void    UpdatePlayGround();
        void    UpdateVScroll();
        void    ShowEntry(sal_uInt16 nPos);
        void    MoveThumbTo(long nNewThumbPos);
        void    Resize();

    public:
                                    OBrowserListBox( Window* pParent, WinBits nWinStyle = WB_DIALOGCONTROL );

                                    ~OBrowserListBox();

        void                        UpdateAll();

        void                        Activate(sal_Bool _bActive = sal_True);

        sal_uInt16                  CalcVisibleLines();
        void                        EnableUpdate();
        void                        DisableUpdate();
        long                        Notify( NotifyEvent& _rNEvt );

        void                        setListener(IPropertyLineListener* _pPLL);

        void                        Clear();

        sal_uInt16                  InsertEntry( const OLineDescriptor&, sal_uInt16 nPos = EDITOR_LIST_APPEND );
        sal_Bool                    RemoveEntry( const ::rtl::OUString& _rName );
        void                        ChangeEntry( const OLineDescriptor&, sal_uInt16 nPos );

        void                        SetPropertyValue( const ::rtl::OUString& rEntryName, const ::com::sun::star::uno::Any& rValue );
        ::com::sun::star::uno::Any  GetPropertyValue( const ::rtl::OUString& rEntryName ) const;
        sal_uInt16                  GetPropertyPos( const ::rtl::OUString& rEntryName ) const;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >
                                    GetPropertyControl( const ::rtl::OUString& rEntryName );
        void                        EnablePropertyControls( const ::rtl::OUString& _rEntryName, sal_Int16 _nControls, bool _bEnable );
        void                        EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable );
        sal_Bool                    IsPropertyInputEnabled( const ::rtl::OUString& _rEntryName ) const;

        // #95343# --------------------------
        sal_Int32                   GetMinimumWidth();

        sal_Bool    IsModified( ) const;
        void        CommitModified( );

    protected:
        // IControlContext
        virtual void SAL_CALL focusGained( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL controlValueChanged( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL activateNextControl( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& CurrentControl ) throw (::com::sun::star::uno::RuntimeException);

        // IButtonClickListener
        void    buttonClicked( OBrowserLine* _pLine, sal_Bool _bPrimary );

    private:
        DECL_LINK( ScrollHdl, ScrollBar* );

        /** retrieves the index of a given control in our line list
            @param _rxControl
                The control to lookup. Must denote a control of one of the lines in ->m_aLines
        */
        sal_uInt16  impl_getControlPos( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& _rxControl ) const;

        /** retrieves (a reference to) the ->ListBoxLine for a given control
            @param _rxControl
                The control to lookup. Must denote a control of one of the lines in ->m_aLines
        */
        inline const ListBoxLine&
                    impl_getControlLine( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& _rxControl ) const
        {
            return m_aOrderedLines[ impl_getControlPos( _rxControl ) ]->second;
        }

        /** sets the given property value at the given control, after converting it as necessary
            @param _rLine
                The line whose at which the value is to be set.
            @param _rPropertyValue
                the property value to set. If it's not compatible with the control value,
                it will be converted, using <member>XPropertyHandler::convertToControlValue</member>
        */
        void        impl_setControlAsPropertyValue( const ListBoxLine& _rLine, const ::com::sun::star::uno::Any& _rPropertyValue );

        /** retrieves the value for the given control, as a property value, after converting it as necessary
            @param _rLine
                The line whose at which the value is to be set.
        */
        ::com::sun::star::uno::Any
                    impl_getControlAsPropertyValue( const ListBoxLine& _rLine ) const;

        /** retrieves the ->BrowserLinePointer for a given entry name
            @param  _rEntryName
                the name whose line is to be looked up
            @param  _out_rpLine
                contains, upon return, the found browser line, if any
            @return
                <TRUE/> if and only if a non-<NULL/> line for the given entry name could be
                found.
        */
        bool        impl_getBrowserLineForName( const ::rtl::OUString& _rEntryName, BrowserLinePointer& _out_rpLine ) const;
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_

<commit_msg>INTEGRATION: CWS long2int (1.7.34); FILE MERGED 2006/03/17 19:23:25 pjanik 1.7.34.2: RESYNC: (1.7-1.8); FILE MERGED 2005/10/26 18:07:11 kendy 1.7.34.1: #i56715# Trivial long/ULONG -> sal_Int32/sal_uInt32 patches extracted from ooo64bit02 CWS.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserlistbox.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: vg $ $Date: 2006-03-31 09:24:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_
#define _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERLINE_HXX_
#include "browserline.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_PCRCOMMON_HXX_
#include "pcrcommon.hxx"
#endif

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_INSPECTION_XPROPERTYCONTROL_HPP_
#include <com/sun/star/inspection/XPropertyControl.hpp>
#endif
#ifndef _COM_SUN_STAR_INSPECTION_XPROPERTYHANDLER_HPP_
#include <com/sun/star/inspection/XPropertyHandler.hpp>
#endif
/** === end UNO includes === **/

#ifndef _SV_SCRBAR_HXX
#include <vcl/scrbar.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#include <set>
#include <vector>
#include <hash_map>
#include <boost/shared_ptr.hpp>

//............................................................................
namespace pcr
{
//............................................................................

    class IPropertyLineListener;
    struct OLineDescriptor;
    class PropertyControlContext_Impl;

    //========================================================================
    //= administrative structures for OBrowserListBox
    //========================================================================
    typedef ::boost::shared_ptr< OBrowserLine > BrowserLinePointer;
    struct ListBoxLine
    {
        BrowserLinePointer                      pLine;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyHandler >
                                                xHandler;

        ListBoxLine() { }
        ListBoxLine( BrowserLinePointer _pLine, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyHandler >& _rxHandler )
            :pLine( _pLine )
            ,xHandler( _rxHandler )
        {
        }
    };
    typedef ::std::hash_map< ::rtl::OUString, ListBoxLine, ::rtl::OUStringHash >    ListBoxLines;
    typedef ::std::vector< ListBoxLines::iterator >                                 OrderedListBoxLines;

    //========================================================================
    //= IControlContext
    //========================================================================
    /** non-UNO version of XPropertyControlContext
    */
    class SAL_NO_VTABLE IControlContext
    {
    public:
        virtual void SAL_CALL focusGained( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException) = 0;
        virtual void SAL_CALL controlValueChanged( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException) = 0;
        virtual void SAL_CALL activateNextControl( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& CurrentControl ) throw (::com::sun::star::uno::RuntimeException) = 0;
    };

    //========================================================================
    //= OBrowserListBox
    //========================================================================
    class OBrowserListBox   :public Control
                            ,public IButtonClickListener
                            ,public IControlContext
                            ,public PcrClient
    {
    protected:
        Window                      m_aPlayGround;
        ScrollBar                   m_aVScroll;
        ListBoxLines                m_aLines;
        OrderedListBoxLines         m_aOrderedLines;
        IPropertyLineListener*      m_pLineListener;
        long                        m_nYOffset;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >
                                    m_xActiveControl;
        sal_uInt16                  m_nTheNameSize;
        sal_uInt16                  m_nRowHeight;
        ::std::set< sal_uInt16 >    m_aOutOfDateLines;
        sal_Bool                    m_bIsActive : 1;
        sal_Bool                    m_bUpdate : 1;
        ::rtl::Reference< PropertyControlContext_Impl >
                                    m_pControlContextImpl;

    protected:
        void    PositionLine( sal_uInt16 _nIndex );
        void    UpdatePosNSize();
        void    UpdatePlayGround();
        void    UpdateVScroll();
        void    ShowEntry(sal_uInt16 nPos);
        void    MoveThumbTo(sal_Int32 nNewThumbPos);
        void    Resize();

    public:
                                    OBrowserListBox( Window* pParent, WinBits nWinStyle = WB_DIALOGCONTROL );

                                    ~OBrowserListBox();

        void                        UpdateAll();

        void                        Activate(sal_Bool _bActive = sal_True);

        sal_uInt16                  CalcVisibleLines();
        void                        EnableUpdate();
        void                        DisableUpdate();
        long                        Notify( NotifyEvent& _rNEvt );

        void                        setListener(IPropertyLineListener* _pPLL);

        void                        Clear();

        sal_uInt16                  InsertEntry( const OLineDescriptor&, sal_uInt16 nPos = EDITOR_LIST_APPEND );
        sal_Bool                    RemoveEntry( const ::rtl::OUString& _rName );
        void                        ChangeEntry( const OLineDescriptor&, sal_uInt16 nPos );

        void                        SetPropertyValue( const ::rtl::OUString& rEntryName, const ::com::sun::star::uno::Any& rValue );
        ::com::sun::star::uno::Any  GetPropertyValue( const ::rtl::OUString& rEntryName ) const;
        sal_uInt16                  GetPropertyPos( const ::rtl::OUString& rEntryName ) const;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >
                                    GetPropertyControl( const ::rtl::OUString& rEntryName );
        void                        EnablePropertyControls( const ::rtl::OUString& _rEntryName, sal_Int16 _nControls, bool _bEnable );
        void                        EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable );
        sal_Bool                    IsPropertyInputEnabled( const ::rtl::OUString& _rEntryName ) const;

        // #95343# --------------------------
        sal_Int32                   GetMinimumWidth();

        sal_Bool    IsModified( ) const;
        void        CommitModified( );

    protected:
        // IControlContext
        virtual void SAL_CALL focusGained( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL controlValueChanged( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& Control ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL activateNextControl( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& CurrentControl ) throw (::com::sun::star::uno::RuntimeException);

        // IButtonClickListener
        void    buttonClicked( OBrowserLine* _pLine, sal_Bool _bPrimary );

    private:
        DECL_LINK( ScrollHdl, ScrollBar* );

        /** retrieves the index of a given control in our line list
            @param _rxControl
                The control to lookup. Must denote a control of one of the lines in ->m_aLines
        */
        sal_uInt16  impl_getControlPos( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& _rxControl ) const;

        /** retrieves (a reference to) the ->ListBoxLine for a given control
            @param _rxControl
                The control to lookup. Must denote a control of one of the lines in ->m_aLines
        */
        inline const ListBoxLine&
                    impl_getControlLine( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >& _rxControl ) const
        {
            return m_aOrderedLines[ impl_getControlPos( _rxControl ) ]->second;
        }

        /** sets the given property value at the given control, after converting it as necessary
            @param _rLine
                The line whose at which the value is to be set.
            @param _rPropertyValue
                the property value to set. If it's not compatible with the control value,
                it will be converted, using <member>XPropertyHandler::convertToControlValue</member>
        */
        void        impl_setControlAsPropertyValue( const ListBoxLine& _rLine, const ::com::sun::star::uno::Any& _rPropertyValue );

        /** retrieves the value for the given control, as a property value, after converting it as necessary
            @param _rLine
                The line whose at which the value is to be set.
        */
        ::com::sun::star::uno::Any
                    impl_getControlAsPropertyValue( const ListBoxLine& _rLine ) const;

        /** retrieves the ->BrowserLinePointer for a given entry name
            @param  _rEntryName
                the name whose line is to be looked up
            @param  _out_rpLine
                contains, upon return, the found browser line, if any
            @return
                <TRUE/> if and only if a non-<NULL/> line for the given entry name could be
                found.
        */
        bool        impl_getBrowserLineForName( const ::rtl::OUString& _rEntryName, BrowserLinePointer& _out_rpLine ) const;
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: propertyeditor.hxx,v $
 * $Revision: 1.17 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_
#define _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

#include "pcrcommon.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/inspection/XPropertyControl.hpp>
/** === end UNO includes === **/
#include <vcl/tabctrl.hxx>
#include <comphelper/stl_types.hxx>
#include <boost/mem_fn.hpp>
#include <map>

//............................................................................
namespace pcr
{
//............................................................................

    class IPropertyLineListener;
    class IPropertyControlObserver;
    class OBrowserPage;
    struct OLineDescriptor;
    class OBrowserListBox;

    //========================================================================
    //= OPropertyEditor
    //========================================================================
    class OPropertyEditor : public Control
    {
    private:
        typedef ::std::map< ::rtl::OUString, sal_uInt16 >   MapStringToPageId;
        struct HiddenPage
        {
            sal_uInt16  nPos;
            TabPage*    pPage;
            HiddenPage() : nPos( 0 ), pPage( NULL ) { }
            HiddenPage( sal_uInt16 _nPos, TabPage* _pPage ) : nPos( _nPos ), pPage( _pPage ) { }
        };

    private:
        TabControl                  m_aTabControl;
        IPropertyLineListener*      m_pListener;
        IPropertyControlObserver*   m_pObserver;
        sal_uInt16                  m_nNextId;
        Link                        m_aPageActivationHandler;
        bool                        m_bHasHelpSection;
        sal_Int32                   m_nMinHelpLines;
        sal_Int32                   m_nMaxHelpLines;

        MapStringToPageId                       m_aPropertyPageIds;
        ::std::map< sal_uInt16, HiddenPage >    m_aHiddenPages;

    protected:
        void                        Resize();
        void                        GetFocus();

    public:
                                    OPropertyEditor (Window* pParent, WinBits nWinStyle = WB_DIALOGCONTROL);

                                    ~OPropertyEditor();

        sal_uInt16                  CalcVisibleLines();
        void                        EnableUpdate();
        void                        DisableUpdate();

        void                        SetLineListener( IPropertyLineListener* );
        void                        SetControlObserver( IPropertyControlObserver* );

        void                        EnableHelpSection( bool _bEnable );
        bool                        HasHelpSection() const;
        void                        SetHelpText( const ::rtl::OUString& _rHelpText );
        void                        SetHelpLineLimites( sal_Int32 _nMinLines, sal_Int32 _nMaxLines );

        void                        SetHelpId( sal_uInt32 nHelpId );
        sal_uInt16                  AppendPage( const String& r, const SmartId& _rHelpId );
        void                        SetPage( sal_uInt16 );
        void                        RemovePage(sal_uInt16 nID);
        sal_uInt16                  GetCurPage();
        void                        ClearAll();

        void                        SetPropertyValue(const ::rtl::OUString& _rEntryName, const ::com::sun::star::uno::Any& _rValue );
        ::com::sun::star::uno::Any  GetPropertyValue(const ::rtl::OUString& rEntryName ) const;
        sal_uInt16                  GetPropertyPos(const ::rtl::OUString& rEntryName ) const;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >
                                    GetPropertyControl( const ::rtl::OUString& rEntryName );
        void                        EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable );
        void                        EnablePropertyControls( const ::rtl::OUString& _rEntryName, sal_Int16 _nControls, bool _bEnable );
        sal_Bool                    IsPropertyInputEnabled( const ::rtl::OUString& _rEntryName ) const;

        void                        ShowPropertyPage( sal_uInt16 _nPageId, bool _bShow );

        sal_uInt16                  InsertEntry( const OLineDescriptor&, sal_uInt16 _nPageId, sal_uInt16 nPos = EDITOR_LIST_APPEND );
        void                        RemoveEntry( const ::rtl::OUString& _rName );
        void                        ChangeEntry( const OLineDescriptor& );

        void    setPageActivationHandler(const Link& _rHdl) { m_aPageActivationHandler = _rHdl; }
        Link    getPageActivationHandler() const { return m_aPageActivationHandler; }

        // #95343# -------------------------------
        sal_Int32 getMinimumWidth();
        sal_Int32 getMinimumHeight();

        void                        CommitModified();

    protected:
        using Window::SetHelpText;
        using Window::Update;

    private:
        OBrowserPage* getPage( sal_uInt16& _rPageId );
        const OBrowserPage* getPage( sal_uInt16& _rPageId ) const;

        OBrowserPage* getPage( const ::rtl::OUString& _rPropertyName );
        const OBrowserPage* getPage( const ::rtl::OUString& _rPropertyName ) const;

        void Update(const ::std::mem_fun_t<void,OBrowserListBox>& _aUpdateFunction);

        typedef void (OPropertyEditor::*PageOperation)( OBrowserPage&, const void* );
        void    forEachPage( PageOperation _pOperation, const void* _pArgument = NULL );

        void    setPageLineListener( OBrowserPage& _rPage, const void* );
        void    setPageControlObserver( OBrowserPage& _rPage, const void* );
        void    enableHelpSection( OBrowserPage& _rPage, const void* );
        void    setHelpSectionText( OBrowserPage& _rPage, const void* _pPointerToOUString );
        void    setHelpLineLimits( OBrowserPage& _rPage, const void* );

    protected:
        DECL_LINK(OnPageDeactivate, TabControl*);
        DECL_LINK(OnPageActivate, TabControl*);
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

<commit_msg>INTEGRATION: CWS mba30patches01 (1.16.4); FILE MERGED 2008/04/23 10:49:57 mba 1.16.4.2: RESYNC: (1.16-1.17); FILE MERGED 2008/03/18 15:41:00 mba 1.16.4.1: #i86365#: remove unused code<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: propertyeditor.hxx,v $
 * $Revision: 1.18 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_
#define _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

#include "pcrcommon.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/inspection/XPropertyControl.hpp>
/** === end UNO includes === **/
#include <vcl/tabctrl.hxx>
#include <comphelper/stl_types.hxx>
#include <boost/mem_fn.hpp>
#include <map>

//............................................................................
namespace pcr
{
//............................................................................

    class IPropertyLineListener;
    class IPropertyControlObserver;
    class OBrowserPage;
    struct OLineDescriptor;
    class OBrowserListBox;

    //========================================================================
    //= OPropertyEditor
    //========================================================================
    class OPropertyEditor : public Control
    {
    private:
        typedef ::std::map< ::rtl::OUString, sal_uInt16 >   MapStringToPageId;
        struct HiddenPage
        {
            sal_uInt16  nPos;
            TabPage*    pPage;
            HiddenPage() : nPos( 0 ), pPage( NULL ) { }
            HiddenPage( sal_uInt16 _nPos, TabPage* _pPage ) : nPos( _nPos ), pPage( _pPage ) { }
        };

    private:
        TabControl                  m_aTabControl;
        IPropertyLineListener*      m_pListener;
        IPropertyControlObserver*   m_pObserver;
        sal_uInt16                  m_nNextId;
        Link                        m_aPageActivationHandler;
        bool                        m_bHasHelpSection;
        sal_Int32                   m_nMinHelpLines;
        sal_Int32                   m_nMaxHelpLines;

        MapStringToPageId                       m_aPropertyPageIds;
        ::std::map< sal_uInt16, HiddenPage >    m_aHiddenPages;

    protected:
        void                        Resize();
        void                        GetFocus();

    public:
                                    OPropertyEditor (Window* pParent, WinBits nWinStyle = WB_DIALOGCONTROL);

                                    ~OPropertyEditor();

        void                        EnableUpdate();
        void                        DisableUpdate();

        void                        SetLineListener( IPropertyLineListener* );
        void                        SetControlObserver( IPropertyControlObserver* );

        void                        EnableHelpSection( bool _bEnable );
        bool                        HasHelpSection() const;
        void                        SetHelpText( const ::rtl::OUString& _rHelpText );
        void                        SetHelpLineLimites( sal_Int32 _nMinLines, sal_Int32 _nMaxLines );

        void                        SetHelpId( sal_uInt32 nHelpId );
        sal_uInt16                  AppendPage( const String& r, const SmartId& _rHelpId );
        void                        SetPage( sal_uInt16 );
        void                        RemovePage(sal_uInt16 nID);
        sal_uInt16                  GetCurPage();
        void                        ClearAll();

        void                        SetPropertyValue(const ::rtl::OUString& _rEntryName, const ::com::sun::star::uno::Any& _rValue );
        ::com::sun::star::uno::Any  GetPropertyValue(const ::rtl::OUString& rEntryName ) const;
        sal_uInt16                  GetPropertyPos(const ::rtl::OUString& rEntryName ) const;
        ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControl >
                                    GetPropertyControl( const ::rtl::OUString& rEntryName );
        void                        EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable );
        void                        EnablePropertyControls( const ::rtl::OUString& _rEntryName, sal_Int16 _nControls, bool _bEnable );

        void                        ShowPropertyPage( sal_uInt16 _nPageId, bool _bShow );

        sal_uInt16                  InsertEntry( const OLineDescriptor&, sal_uInt16 _nPageId, sal_uInt16 nPos = EDITOR_LIST_APPEND );
        void                        RemoveEntry( const ::rtl::OUString& _rName );
        void                        ChangeEntry( const OLineDescriptor& );

        void    setPageActivationHandler(const Link& _rHdl) { m_aPageActivationHandler = _rHdl; }
        Link    getPageActivationHandler() const { return m_aPageActivationHandler; }

        // #95343# -------------------------------
        sal_Int32 getMinimumWidth();
        sal_Int32 getMinimumHeight();

        void                        CommitModified();

    protected:
        using Window::SetHelpText;
        using Window::Update;

    private:
        OBrowserPage* getPage( sal_uInt16& _rPageId );
        const OBrowserPage* getPage( sal_uInt16& _rPageId ) const;

        OBrowserPage* getPage( const ::rtl::OUString& _rPropertyName );
        const OBrowserPage* getPage( const ::rtl::OUString& _rPropertyName ) const;

        void Update(const ::std::mem_fun_t<void,OBrowserListBox>& _aUpdateFunction);

        typedef void (OPropertyEditor::*PageOperation)( OBrowserPage&, const void* );
        void    forEachPage( PageOperation _pOperation, const void* _pArgument = NULL );

        void    setPageLineListener( OBrowserPage& _rPage, const void* );
        void    setPageControlObserver( OBrowserPage& _rPage, const void* );
        void    enableHelpSection( OBrowserPage& _rPage, const void* );
        void    setHelpSectionText( OBrowserPage& _rPage, const void* _pPointerToOUString );
        void    setHelpLineLimits( OBrowserPage& _rPage, const void* );

    protected:
        DECL_LINK(OnPageDeactivate, TabControl*);
        DECL_LINK(OnPageActivate, TabControl*);
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  toyLeg_example.cpp                        *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Matt S. DeMers                                                  *
 *                                                                            *
 * Licensed 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.                                             *
 * -------------------------------------------------------------------------- */

/*
 *  Below is an example of an OpenSim application that provides its own
 *  main() routine.  This application acts as an example for utilizing the
 *  ControllabeSpring actuator.
 */

// Author:  Matt DeMers

//==============================================================================
//==============================================================================
#include "PistonActuator.h"
#include "ControllableSpring.h"
#include <OpenSim/OpenSim.h>
#include "OpenSim/Common/STOFileAdapter.h"

using namespace OpenSim;
using namespace SimTK;

//______________________________________________________________________________
/**
 * Run a simulation of block sliding with contact on by two muscles sliding with contact
 */
int main()
{

    try {
        // Create a new OpenSim model
        Model osimModel;
        osimModel.setName("osimModel");
        osimModel.setAuthors("Matt DeMers");

        double Pi = SimTK::Pi;

        // Get the ground body
        Ground& ground = osimModel.updGround();
        ground.attachGeometry(new Mesh("checkered_floor.vtp"));

        // create linkage body
        double linkageMass = 0.001, linkageLength = 0.5, linkageDiameter = 0.06;

        Vec3 linkageDimensions(linkageDiameter, linkageLength, linkageDiameter);
        Vec3 linkageMassCenter(0,linkageLength/2,0);
        Inertia linkageInertia = Inertia::cylinderAlongY(linkageDiameter/2.0, linkageLength/2.0);

        OpenSim::Body* linkage1 = new OpenSim::Body("linkage1", linkageMass, linkageMassCenter, linkageMass*linkageInertia);
        linkage1->attachGeometry(new Sphere(0.1));

        // Graphical representation
        Cylinder cyl(linkageDiameter/2, linkageLength);
        Frame* cyl1Frame = new PhysicalOffsetFrame(*linkage1,
            Transform(Vec3(0.0, linkageLength / 2.0, 0.0)));
        cyl1Frame->setName("Cyl1_frame");
        cyl1Frame->attachGeometry(cyl.clone());
        osimModel.addFrame(cyl1Frame);

        // Create a second linkage body as a clone of the first
        OpenSim::Body* linkage2 = linkage1->clone();
        linkage2->setName("linkage2");
        Frame* cyl2Frame = new PhysicalOffsetFrame(*linkage2,
            Transform(Vec3(0.0, linkageLength / 2.0, 0.0)));
        cyl2Frame->setName("Cyl2_frame");
        osimModel.addFrame(cyl2Frame);

        // Create a block to be the pelvis
        double blockMass = 20.0, blockSideLength = 0.2;
        Vec3 blockMassCenter(0);
        Inertia blockInertia = blockMass*Inertia::brick(blockSideLength, blockSideLength, blockSideLength);
        OpenSim::Body *block = new OpenSim::Body("block", blockMass, blockMassCenter, blockInertia);
        block->attachGeometry(new Brick(SimTK::Vec3(0.05, 0.05, 0.05)));

        // Create 1 degree-of-freedom pin joints between the bodies to create a kinematic chain from ground through the block
        Vec3 orientationInGround(0), locationInGround(0), locationInParent(0.0, linkageLength, 0.0), orientationInChild(0), locationInChild(0);

        PinJoint *ankle = new PinJoint("ankle", ground, locationInGround, orientationInGround, *linkage1,
            locationInChild, orientationInChild);

        PinJoint *knee = new PinJoint("knee", *linkage1, locationInParent, orientationInChild, *linkage2,
            locationInChild, orientationInChild);

        PinJoint *hip = new PinJoint("hip", *linkage2, locationInParent, orientationInChild, *block,
            locationInChild, orientationInChild);

        double range[2] = {-SimTK::Pi*2, SimTK::Pi*2};
        CoordinateSet& ankleCoordinateSet = ankle->upd_CoordinateSet();
        ankleCoordinateSet[0].setName("q1");
        ankleCoordinateSet[0].setRange(range);

        CoordinateSet& kneeCoordinateSet = knee->upd_CoordinateSet();
        kneeCoordinateSet[0].setName("q2");
        kneeCoordinateSet[0].setRange(range);

        CoordinateSet& hipCoordinateSet = hip->upd_CoordinateSet();
        hipCoordinateSet[0].setName("q3");
        hipCoordinateSet[0].setRange(range);

        // Add the bodies to the model
        osimModel.addBody(linkage1);
        osimModel.addBody(linkage2);
        osimModel.addBody(block);

        // Add the joints to the model
        osimModel.addJoint(ankle);
        osimModel.addJoint(knee);
        osimModel.addJoint(hip);
        // Define constraints on the model
        //  Add a point on line constraint to limit the block to vertical motion

        Vec3 lineDirection(0,1,0), pointOnLine(0,0,0), pointOnBlock(0);
        PointOnLineConstraint *lineConstraint = new PointOnLineConstraint(ground, lineDirection, pointOnLine, *block, pointOnBlock);
        osimModel.addConstraint(lineConstraint);

        // Add PistonActuator between the first linkage and the block
        Vec3 pointOnBodies(0);
        PistonActuator *piston = new PistonActuator();
        piston->setName("piston");
        piston->setBodyA(linkage1);
        piston->setBodyB(block);
        piston->setPointA(pointOnBodies);
        piston->setPointB(pointOnBodies);
        piston->setOptimalForce(200.0);
        piston->setPointsAreGlobal(false);

        osimModel.addForce(piston);
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Added ControllableSpring between the first linkage and the second block
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        ControllableSpring *spring = new ControllableSpring;
        spring->setName("spring");
        spring->setBodyA(block);
        spring->setBodyB(linkage1);
        spring->setPointA(pointOnBodies);
        spring->setPointB(pointOnBodies);
        spring->setOptimalForce(2000.0);
        spring->setPointsAreGlobal(false);
        spring->setRestLength(0.8);

        osimModel.addForce(spring);

        // define the simulation times
        double t0(0.0), tf(15);

        // create a controller to control the piston and spring actuators
        // the prescribed controller sets the controls as functions of time
        PrescribedController *legController = new PrescribedController();
        // give the legController control over all (two) model actuators
        legController->setActuators(osimModel.updActuators());

        // specify some control nodes for spring stiffness control
        double t[] = {0.0, 4.0, 7.0,  10.0, 15.0};
        double x[] = {1.0, 1.0, 0.25,  0.25, 5.0};

        // specify the control function for each actuator
        legController->prescribeControlForActuator("piston", new Constant(0.1));
        legController->prescribeControlForActuator("spring", new PiecewiseLinearFunction(5, t, x));

        // add the controller to the model
        osimModel.addController(legController);

        // define the acceleration due to gravity
        osimModel.setGravity(Vec3(0, -9.80665, 0));

        // enable the model visualizer see the model in action, which can be
        // useful for debugging
        osimModel.setUseVisualizer(false);

        // Initialize system
        SimTK::State& si = osimModel.initSystem();

        // Pin joint initial states
        double q1_i = -Pi/4;
        double q2_i = - 2*q1_i;
        CoordinateSet &coordinates = osimModel.updCoordinateSet();
        coordinates[0].setValue(si, q1_i, true);
        coordinates[1].setValue(si,q2_i, true);

        // Setup integrator and manager
        SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem());
        integrator.setAccuracy(1.0e-3);

        ForceReporter *forces = new ForceReporter(&osimModel);
        osimModel.updAnalysisSet().adoptAndAppend(forces);
        Manager manager(osimModel, integrator);

        //Examine the model
        osimModel.printDetailedInfo(si, std::cout);
        // Save the model
        osimModel.print("toyLeg.osim");
        // Print out the initial position and velocity states
        si.getQ().dump("Initial q's");
        si.getU().dump("Initial u's");
        std::cout << "Initial time: " << si.getTime() << std::endl;

        // Integrate
        manager.setInitialTime(t0);
        manager.setFinalTime(tf);
        std::cout<<"\n\nIntegrating from " << t0 << " to " << tf << std::endl;
        manager.integrate(si);

        // Save results
        auto controlsTable = osimModel.getControlsTable();
        STOFileAdapter::write(controlsTable, "SpringActuatedLeg_controls.sto");

        auto statesTable = manager.getStatesTable();
        osimModel.updSimbodyEngine().convertRadiansToDegrees(statesTable);
        STOFileAdapter::write(statesTable,
                              "SpringActuatedLeg_states_degrees.sto");

        auto forcesTable = forces->getForcesTable();
        STOFileAdapter::write(forcesTable, "actuator_forces.sto");
    }
    catch (const std::exception& ex)
    {
        std::cout << "Exception in toyLeg_example: " << ex.what() << std::endl;
        return 1;
    }

    std::cout << "Done." << std::endl;
    return 0;
}
<commit_msg>Remove unused linkageDimensions from toyLeg_example.cpp<commit_after>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  toyLeg_example.cpp                        *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Matt S. DeMers                                                  *
 *                                                                            *
 * Licensed 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.                                             *
 * -------------------------------------------------------------------------- */

/*
 *  Below is an example of an OpenSim application that provides its own
 *  main() routine.  This application acts as an example for utilizing the
 *  ControllabeSpring actuator.
 */

// Author:  Matt DeMers

//==============================================================================
//==============================================================================
#include "PistonActuator.h"
#include "ControllableSpring.h"
#include <OpenSim/OpenSim.h>
#include "OpenSim/Common/STOFileAdapter.h"

using namespace OpenSim;
using namespace SimTK;

//______________________________________________________________________________
/**
 * Run a simulation of block sliding with contact on by two muscles sliding with contact
 */
int main()
{
    try {
        // Create a new OpenSim model
        Model osimModel;
        osimModel.setName("osimModel");
        osimModel.setAuthors("Matt DeMers");

        double Pi = SimTK::Pi;

        // Get the ground body
        Ground& ground = osimModel.updGround();
        ground.attachGeometry(new Mesh("checkered_floor.vtp"));

        // create linkage body
        double linkageMass = 0.001, linkageLength = 0.5, linkageDiameter = 0.06;

        Vec3 linkageMassCenter(0,linkageLength/2,0);
        Inertia linkageInertia = Inertia::cylinderAlongY(linkageDiameter/2.0, linkageLength/2.0);

        OpenSim::Body* linkage1 = new OpenSim::Body("linkage1", linkageMass, linkageMassCenter, linkageMass*linkageInertia);
        linkage1->attachGeometry(new Sphere(0.1));

        // Graphical representation
        Cylinder cyl(linkageDiameter/2, linkageLength);
        Frame* cyl1Frame = new PhysicalOffsetFrame(*linkage1,
            Transform(Vec3(0.0, linkageLength / 2.0, 0.0)));
        cyl1Frame->setName("Cyl1_frame");
        cyl1Frame->attachGeometry(cyl.clone());
        osimModel.addFrame(cyl1Frame);

        // Create a second linkage body as a clone of the first
        OpenSim::Body* linkage2 = linkage1->clone();
        linkage2->setName("linkage2");
        Frame* cyl2Frame = new PhysicalOffsetFrame(*linkage2,
            Transform(Vec3(0.0, linkageLength / 2.0, 0.0)));
        cyl2Frame->setName("Cyl2_frame");
        osimModel.addFrame(cyl2Frame);

        // Create a block to be the pelvis
        double blockMass = 20.0, blockSideLength = 0.2;
        Vec3 blockMassCenter(0);
        Inertia blockInertia = blockMass*Inertia::brick(blockSideLength, blockSideLength, blockSideLength);
        OpenSim::Body *block = new OpenSim::Body("block", blockMass, blockMassCenter, blockInertia);
        block->attachGeometry(new Brick(SimTK::Vec3(0.05, 0.05, 0.05)));

        // Create 1 degree-of-freedom pin joints between the bodies to create a kinematic chain from ground through the block
        Vec3 orientationInGround(0), locationInGround(0), locationInParent(0.0, linkageLength, 0.0), orientationInChild(0), locationInChild(0);

        PinJoint *ankle = new PinJoint("ankle", ground, locationInGround, orientationInGround, *linkage1,
            locationInChild, orientationInChild);

        PinJoint *knee = new PinJoint("knee", *linkage1, locationInParent, orientationInChild, *linkage2,
            locationInChild, orientationInChild);

        PinJoint *hip = new PinJoint("hip", *linkage2, locationInParent, orientationInChild, *block,
            locationInChild, orientationInChild);

        double range[2] = {-SimTK::Pi*2, SimTK::Pi*2};
        CoordinateSet& ankleCoordinateSet = ankle->upd_CoordinateSet();
        ankleCoordinateSet[0].setName("q1");
        ankleCoordinateSet[0].setRange(range);

        CoordinateSet& kneeCoordinateSet = knee->upd_CoordinateSet();
        kneeCoordinateSet[0].setName("q2");
        kneeCoordinateSet[0].setRange(range);

        CoordinateSet& hipCoordinateSet = hip->upd_CoordinateSet();
        hipCoordinateSet[0].setName("q3");
        hipCoordinateSet[0].setRange(range);

        // Add the bodies to the model
        osimModel.addBody(linkage1);
        osimModel.addBody(linkage2);
        osimModel.addBody(block);

        // Add the joints to the model
        osimModel.addJoint(ankle);
        osimModel.addJoint(knee);
        osimModel.addJoint(hip);
        // Define constraints on the model
        //  Add a point on line constraint to limit the block to vertical motion

        Vec3 lineDirection(0,1,0), pointOnLine(0,0,0), pointOnBlock(0);
        PointOnLineConstraint *lineConstraint = new PointOnLineConstraint(ground, lineDirection, pointOnLine, *block, pointOnBlock);
        osimModel.addConstraint(lineConstraint);

        // Add PistonActuator between the first linkage and the block
        Vec3 pointOnBodies(0);
        PistonActuator *piston = new PistonActuator();
        piston->setName("piston");
        piston->setBodyA(linkage1);
        piston->setBodyB(block);
        piston->setPointA(pointOnBodies);
        piston->setPointB(pointOnBodies);
        piston->setOptimalForce(200.0);
        piston->setPointsAreGlobal(false);

        osimModel.addForce(piston);
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Added ControllableSpring between the first linkage and the second block
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        ControllableSpring *spring = new ControllableSpring;
        spring->setName("spring");
        spring->setBodyA(block);
        spring->setBodyB(linkage1);
        spring->setPointA(pointOnBodies);
        spring->setPointB(pointOnBodies);
        spring->setOptimalForce(2000.0);
        spring->setPointsAreGlobal(false);
        spring->setRestLength(0.8);

        osimModel.addForce(spring);

        // define the simulation times
        double t0(0.0), tf(15);

        // create a controller to control the piston and spring actuators
        // the prescribed controller sets the controls as functions of time
        PrescribedController *legController = new PrescribedController();
        // give the legController control over all (two) model actuators
        legController->setActuators(osimModel.updActuators());

        // specify some control nodes for spring stiffness control
        double t[] = {0.0, 4.0, 7.0,  10.0, 15.0};
        double x[] = {1.0, 1.0, 0.25,  0.25, 5.0};

        // specify the control function for each actuator
        legController->prescribeControlForActuator("piston", new Constant(0.1));
        legController->prescribeControlForActuator("spring", new PiecewiseLinearFunction(5, t, x));

        // add the controller to the model
        osimModel.addController(legController);

        // define the acceleration due to gravity
        osimModel.setGravity(Vec3(0, -9.80665, 0));

        // enable the model visualizer see the model in action, which can be
        // useful for debugging
        osimModel.setUseVisualizer(false);

        // Initialize system
        SimTK::State& si = osimModel.initSystem();

        // Pin joint initial states
        double q1_i = -Pi/4;
        double q2_i = - 2*q1_i;
        CoordinateSet &coordinates = osimModel.updCoordinateSet();
        coordinates[0].setValue(si, q1_i, true);
        coordinates[1].setValue(si,q2_i, true);

        // Setup integrator and manager
        SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem());
        integrator.setAccuracy(1.0e-3);

        ForceReporter *forces = new ForceReporter(&osimModel);
        osimModel.updAnalysisSet().adoptAndAppend(forces);
        Manager manager(osimModel, integrator);

        //Examine the model
        osimModel.printDetailedInfo(si, std::cout);
        // Save the model
        osimModel.print("toyLeg.osim");
        // Print out the initial position and velocity states
        si.getQ().dump("Initial q's");
        si.getU().dump("Initial u's");
        std::cout << "Initial time: " << si.getTime() << std::endl;

        // Integrate
        manager.setInitialTime(t0);
        manager.setFinalTime(tf);
        std::cout<<"\n\nIntegrating from " << t0 << " to " << tf << std::endl;
        manager.integrate(si);

        // Save results
        auto controlsTable = osimModel.getControlsTable();
        STOFileAdapter::write(controlsTable, "SpringActuatedLeg_controls.sto");

        auto statesTable = manager.getStatesTable();
        osimModel.updSimbodyEngine().convertRadiansToDegrees(statesTable);
        STOFileAdapter::write(statesTable,
                              "SpringActuatedLeg_states_degrees.sto");

        auto forcesTable = forces->getForcesTable();
        STOFileAdapter::write(forcesTable, "actuator_forces.sto");
    }
    catch (const std::exception& ex)
    {
        std::cout << "Exception in toyLeg_example: " << ex.what() << std::endl;
        return 1;
    }

    std::cout << "Done." << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>#include "multiplayer_proxy.h"
#include "multiplayer_internal.h"

GameServerProxy::GameServerProxy(sf::IpAddress hostname, int hostPort, string password, int listenPort)
: password(password)
{
    mainSocket.connect(hostname, hostPort);
    mainSocket.setBlocking(false);
    listenSocket.listen(listenPort);
    listenSocket.setBlocking(false);

    newSocket = std::unique_ptr<TcpSocket>(new TcpSocket());
    newSocket->setBlocking(false);

    lastReceiveTime.restart();
}

GameServerProxy::~GameServerProxy()
{
}

void GameServerProxy::destroy()
{
    clientList.clear();
}

void GameServerProxy::update(float delta)
{
    mainSocket.update();
    sf::Packet packet;
    sf::TcpSocket::Status socketStatus;
    while((socketStatus = mainSocket.receive(packet)) == sf::TcpSocket::Done)
    {
        lastReceiveTime.restart();
        command_t command;
        packet >> command;
        switch(command)
        {
        case CMD_REQUEST_AUTH:
            {
                bool requirePassword;
                packet >> serverVersion >> requirePassword;

                sf::Packet reply;
                reply << CMD_CLIENT_SEND_AUTH << int32_t(serverVersion) << string(password);
                mainSocket.send(reply);
            }
            break;
        case CMD_SET_CLIENT_ID:
            packet >> clientId;
            break;
        case CMD_ALIVE:
            {
                sf::Packet reply;
                reply << CMD_ALIVE_RESP;
                mainSocket.send(reply);
            }
            sendAll(packet);
            break;
        case CMD_CREATE:
        case CMD_DELETE:
        case CMD_UPDATE_VALUE:
        case CMD_SET_GAME_SPEED:
        case CMD_SERVER_COMMAND:
            sendAll(packet);
            break;
        case CMD_SET_PROXY_CLIENT_ID:
            {
                int32_t tempId, clientId;
                packet >> tempId >> clientId;
                for(auto& info : clientList)
                {
                    if (!info.validClient && info.clientId == tempId)
                    {
                        info.validClient = true;
                        info.clientId = clientId;
                        info.receiveState = CRS_Main;
                        {
                            sf::Packet packet;
                            packet << CMD_SET_CLIENT_ID << info.clientId;
                            info.socket->send(packet);
                        }
                    }
                }
            }
            break;
        }
    }

    if (socketStatus == sf::TcpSocket::Disconnected || lastReceiveTime.getElapsedTime().asSeconds() > noDataDisconnectTime)
    {
        mainSocket.disconnect();
    }

    if (listenSocket.accept(*newSocket))
    {
        ClientInfo info;
        info.socket = std::move(newSocket);
        newSocket = std::unique_ptr<TcpSocket>(new TcpSocket());
        newSocket->setBlocking(false);
        {
            sf::Packet packet;
            packet << CMD_REQUEST_AUTH << int32_t(serverVersion) << bool(password != "");
            info.socket->send(packet);
        }
        clientList.emplace_back(std::move(info));
    }

    for(unsigned int n=0; n<clientList.size(); n++)
    {
        auto& info = clientList[n];
        info.socket->update();
        while(info.socket && (socketStatus = info.socket->receive(packet)) == sf::TcpSocket::Done)
        {
            command_t command;
            packet >> command;
            switch(info.receiveState)
            {
            case CRS_Auth:
                switch(command)
                {
                case CMD_CLIENT_SEND_AUTH:
                    {
                        int32_t clientVersion;
                        string clientPassword;
                        packet >> clientVersion >> clientPassword;
                        if (clientVersion == serverVersion && clientPassword == password)
                        {
                            sf::Packet serverUpdate;
                            serverUpdate << CMD_NEW_PROXY_CLIENT << info.clientId;
                            mainSocket.send(serverUpdate);
                        }
                        else
                        {
                           info.socket->disconnect();
                           info.socket = NULL;
                        }
                    }
                    break;
                case CMD_ALIVE_RESP:
                    break;
                default:
                    LOG(ERROR) << "Unknown command from client: " << command;
                    break;
                }
                break;
            case CRS_Main:
                switch(command)
                {
                case CMD_CLIENT_COMMAND:
                    packet >> info.commandObjectId;
                    info.receiveState = CRS_Command;
                    break;
                case CMD_ALIVE_RESP:
                    break;
                default:
                    LOG(ERROR) << "Unknown command from client: " << command;
                    break;
                }
                break;
            case CRS_Command:
                {
                    sf::Packet mainPacket;
                    mainPacket << CMD_PROXY_CLIENT_COMMAND << info.commandObjectId << info.clientId;
                    mainSocket.send(mainPacket);
                    mainSocket.send(packet);
                }
                info.receiveState = CRS_Main;
                break;
            }
        }
        if (socketStatus == sf::TcpSocket::Disconnected || info.socket == NULL)
        {
            if (info.validClient)
            {
                sf::Packet serverUpdate;
                serverUpdate << CMD_DEL_PROXY_CLIENT << info.clientId;
                mainSocket.send(serverUpdate);
            }
            clientList.erase(clientList.begin() + n);
            n--;
        }
    }
}

void GameServerProxy::sendAll(sf::Packet& packet)
{
    for(auto& info : clientList)
    {
        if (info.validClient && info.socket)
            info.socket->send(packet);
    }
}
<commit_msg>Add some basic logging to the proxy, and shutdown if the proxy gets disconnected.<commit_after>#include "multiplayer_proxy.h"
#include "multiplayer_internal.h"
#include "engine.h"

GameServerProxy::GameServerProxy(sf::IpAddress hostname, int hostPort, string password, int listenPort)
: password(password)
{
    LOG(INFO) << "Starting proxy server";
    if (mainSocket.connect(hostname, hostPort) != sf::Socket::Status::Done)
        LOG(INFO) << "Failed to connect to server";
    else
        LOG(INFO) << "Connected to server";
    mainSocket.setBlocking(false);
    listenSocket.listen(listenPort);
    listenSocket.setBlocking(false);

    newSocket = std::unique_ptr<TcpSocket>(new TcpSocket());
    newSocket->setBlocking(false);

    lastReceiveTime.restart();
}

GameServerProxy::~GameServerProxy()
{
}

void GameServerProxy::destroy()
{
    clientList.clear();
}

void GameServerProxy::update(float delta)
{
    mainSocket.update();
    sf::Packet packet;
    sf::TcpSocket::Status socketStatus;
    while((socketStatus = mainSocket.receive(packet)) == sf::TcpSocket::Done)
    {
        lastReceiveTime.restart();
        command_t command;
        packet >> command;
        switch(command)
        {
        case CMD_REQUEST_AUTH:
            {
                bool requirePassword;
                packet >> serverVersion >> requirePassword;

                sf::Packet reply;
                reply << CMD_CLIENT_SEND_AUTH << int32_t(serverVersion) << string(password);
                mainSocket.send(reply);
            }
            break;
        case CMD_SET_CLIENT_ID:
            packet >> clientId;
            break;
        case CMD_ALIVE:
            {
                sf::Packet reply;
                reply << CMD_ALIVE_RESP;
                mainSocket.send(reply);
            }
            sendAll(packet);
            break;
        case CMD_CREATE:
        case CMD_DELETE:
        case CMD_UPDATE_VALUE:
        case CMD_SET_GAME_SPEED:
        case CMD_SERVER_COMMAND:
            sendAll(packet);
            break;
        case CMD_SET_PROXY_CLIENT_ID:
            {
                int32_t tempId, clientId;
                packet >> tempId >> clientId;
                for(auto& info : clientList)
                {
                    if (!info.validClient && info.clientId == tempId)
                    {
                        info.validClient = true;
                        info.clientId = clientId;
                        info.receiveState = CRS_Main;
                        {
                            sf::Packet packet;
                            packet << CMD_SET_CLIENT_ID << info.clientId;
                            info.socket->send(packet);
                        }
                    }
                }
            }
            break;
        }
    }

    if (socketStatus == sf::TcpSocket::Disconnected || lastReceiveTime.getElapsedTime().asSeconds() > noDataDisconnectTime)
    {
        LOG(INFO) << "Disconnected proxy";
        mainSocket.disconnect();
        engine->shutdown();
    }

    if (listenSocket.accept(*newSocket))
    {
        ClientInfo info;
        info.socket = std::move(newSocket);
        newSocket = std::unique_ptr<TcpSocket>(new TcpSocket());
        newSocket->setBlocking(false);
        {
            sf::Packet packet;
            packet << CMD_REQUEST_AUTH << int32_t(serverVersion) << bool(password != "");
            info.socket->send(packet);
        }
        clientList.emplace_back(std::move(info));
    }

    for(unsigned int n=0; n<clientList.size(); n++)
    {
        auto& info = clientList[n];
        info.socket->update();
        while(info.socket && (socketStatus = info.socket->receive(packet)) == sf::TcpSocket::Done)
        {
            command_t command;
            packet >> command;
            switch(info.receiveState)
            {
            case CRS_Auth:
                switch(command)
                {
                case CMD_CLIENT_SEND_AUTH:
                    {
                        int32_t clientVersion;
                        string clientPassword;
                        packet >> clientVersion >> clientPassword;
                        if (clientVersion == serverVersion && clientPassword == password)
                        {
                            sf::Packet serverUpdate;
                            serverUpdate << CMD_NEW_PROXY_CLIENT << info.clientId;
                            mainSocket.send(serverUpdate);
                        }
                        else
                        {
                           info.socket->disconnect();
                           info.socket = NULL;
                        }
                    }
                    break;
                case CMD_ALIVE_RESP:
                    break;
                default:
                    LOG(ERROR) << "Unknown command from client: " << command;
                    break;
                }
                break;
            case CRS_Main:
                switch(command)
                {
                case CMD_CLIENT_COMMAND:
                    packet >> info.commandObjectId;
                    info.receiveState = CRS_Command;
                    break;
                case CMD_ALIVE_RESP:
                    break;
                default:
                    LOG(ERROR) << "Unknown command from client: " << command;
                    break;
                }
                break;
            case CRS_Command:
                {
                    sf::Packet mainPacket;
                    mainPacket << CMD_PROXY_CLIENT_COMMAND << info.commandObjectId << info.clientId;
                    mainSocket.send(mainPacket);
                    mainSocket.send(packet);
                }
                info.receiveState = CRS_Main;
                break;
            }
        }
        if (socketStatus == sf::TcpSocket::Disconnected || info.socket == NULL)
        {
            if (info.validClient)
            {
                sf::Packet serverUpdate;
                serverUpdate << CMD_DEL_PROXY_CLIENT << info.clientId;
                mainSocket.send(serverUpdate);
            }
            clientList.erase(clientList.begin() + n);
            n--;
        }
    }
}

void GameServerProxy::sendAll(sf::Packet& packet)
{
    for(auto& info : clientList)
    {
        if (info.validClient && info.socket)
            info.socket->send(packet);
    }
}
<|endoftext|>