diff options
39 files changed, 3258 insertions, 822 deletions
diff --git a/comphelper/inc/comphelper/servicedecl.hxx b/comphelper/inc/comphelper/servicedecl.hxx index a11598bdca85..7b77d3ba29e7 100644 --- a/comphelper/inc/comphelper/servicedecl.hxx +++ b/comphelper/inc/comphelper/servicedecl.hxx @@ -169,21 +169,20 @@ template <bool> struct with_args; /// @internal namespace detail { - template <typename ImplT> -class ServiceImpl - : public ::cppu::ImplInheritanceHelper1<ImplT, css::lang::XServiceInfo>, +class OwnServiceImpl + : public ImplT, private ::boost::noncopyable { - typedef ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> BaseT; + typedef ImplT BaseT; public: - ServiceImpl( + OwnServiceImpl( ServiceDecl const& rServiceDecl, css::uno::Sequence<css::uno::Any> const& args, css::uno::Reference<css::uno::XComponentContext> const& xContext ) - : BaseT(args, xContext), m_rServiceDecl(rServiceDecl) {} - ServiceImpl( + :BaseT(args, xContext), m_rServiceDecl(rServiceDecl) {} + OwnServiceImpl( ServiceDecl const& rServiceDecl, css::uno::Reference<css::uno::XComponentContext> const& xContext ) : BaseT(xContext), m_rServiceDecl(rServiceDecl) {} @@ -206,6 +205,22 @@ private: ServiceDecl const& m_rServiceDecl; }; +template <typename ImplT> +class ServiceImpl : public OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > +{ +typedef OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > ServiceImpl_BASE; +public: + ServiceImpl( + ServiceDecl const& rServiceDecl, + css::uno::Sequence<css::uno::Any> const& args, + css::uno::Reference<css::uno::XComponentContext> const& xContext ) + : ServiceImpl_BASE(rServiceDecl, args, xContext) {} + ServiceImpl( + ServiceDecl const& rServiceDecl, + css::uno::Reference<css::uno::XComponentContext> const& xContext ) + : ServiceImpl_BASE(rServiceDecl, xContext) {} +}; + template <typename ServiceImplT> struct PostProcessDefault { css::uno::Reference<css::uno::XInterface> @@ -230,7 +245,7 @@ struct CreateFunc<ImplT, PostProcessFuncT, with_args<false> > { const& xContext ) const { return m_postProcessFunc( - new ServiceImpl<ImplT>( rServiceDecl, xContext ) ); + new ImplT( rServiceDecl, xContext ) ); } }; @@ -247,7 +262,7 @@ struct CreateFunc<ImplT, PostProcessFuncT, with_args<true> > { const& xContext ) const { return m_postProcessFunc( - new ServiceImpl<ImplT>( rServiceDecl, args, xContext ) ); + new ImplT( rServiceDecl, args, xContext ) ); } }; @@ -261,18 +276,17 @@ struct CreateFunc<ImplT, PostProcessFuncT, with_args<true> > { or just (uno::Reference<uno::XComponentContext>) */ template <typename ImplT_, typename WithArgsT = with_args<false> > -struct class_ { +struct serviceimpl_base { typedef ImplT_ ImplT; - typedef detail::ServiceImpl<ImplT_> ServiceImplT; detail::CreateFuncF const m_createFunc; - typedef detail::PostProcessDefault<ServiceImplT> PostProcessDefaultT; + typedef detail::PostProcessDefault<ImplT> PostProcessDefaultT; /** Default ctor. Implementation class without args, expecting component context as single argument. */ - class_() : m_createFunc( + serviceimpl_base() : m_createFunc( detail::CreateFunc<ImplT, PostProcessDefaultT, WithArgsT>( PostProcessDefaultT() ) ) {} @@ -284,11 +298,29 @@ struct class_ { uno::Reference<uno::XInterface> */ template <typename PostProcessFuncT> - explicit class_( PostProcessFuncT const& postProcessFunc ) + explicit serviceimpl_base( PostProcessFuncT const& postProcessFunc ) : m_createFunc( detail::CreateFunc<ImplT, PostProcessFuncT, WithArgsT>( postProcessFunc ) ) {} }; +template <typename ImplT_, typename WithArgsT = with_args<false> > +struct class_ : public serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > +{ + typedef serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > baseT; + /** Default ctor. Implementation class without args, expecting + component context as single argument. + */ + class_() : baseT() {} + template <typename PostProcessFuncT> + /** Ctor to pass a post processing function/functor. + + @tpl PostProcessDefaultT let your compiler deduce this + @param postProcessFunc function/functor that gets the yet unacquired + ImplT_ pointer returning a + uno::Reference<uno::XInterface> + */ + explicit class_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {} +}; // // component_... helpers with arbitrary service declarations: diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx index 237a493452c7..4d629958e5bf 100644 --- a/svl/source/passwordcontainer/passwordcontainer.cxx +++ b/svl/source/passwordcontainer/passwordcontainer.cxx @@ -152,17 +152,10 @@ static vector< ::rtl::OUString > getInfoFromInd( ::rtl::OUString aInd ) static sal_Bool shorterUrl( ::rtl::OUString& aURL ) { sal_Int32 aInd = aURL.lastIndexOf( sal_Unicode( '/' ) ); - - if( aInd > 0 ) + if( aInd > 0 && aURL.indexOf( ::rtl::OUString::createFromAscii( "://" ) ) != aInd-2 ) { - sal_Int32 aPrevInd = aURL.lastIndexOf( sal_Unicode( '/' ), aInd ); - if ( aURL.indexOf( ::rtl::OUString::createFromAscii( "://" ) ) - != aPrevInd - 2 || - aInd != aURL.getLength() - 1 ) - { - aURL = aURL.copy( 0, aInd ); - return sal_True; - } + aURL = aURL.copy( 0, aInd ); + return sal_True; } return sal_False; diff --git a/svtools/inc/svtools/accessiblefactory.hxx b/svtools/inc/svtools/accessiblefactory.hxx index f7cad847edda..f4d8a03ef872 100644 --- a/svtools/inc/svtools/accessiblefactory.hxx +++ b/svtools/inc/svtools/accessiblefactory.hxx @@ -40,6 +40,7 @@ #endif #include "AccessibleBrowseBoxObjType.hxx" #include "accessibletableprovider.hxx" +#include "accessibletable.hxx" namespace com { namespace sun { namespace star { namespace accessibility { @@ -89,6 +90,11 @@ namespace svt const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParent, IAccessibleTableProvider& _rBrowseBox ) const = 0; + virtual table::IAccessibleTableControl* + createAccessibleTableControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParent, + table::IAccessibleTable& _rTable + ) const = 0; virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > createAccessibleIconChoiceCtrl( diff --git a/svtools/inc/svtools/accessibletable.hxx b/svtools/inc/svtools/accessibletable.hxx new file mode 100755 index 000000000000..0e3f08bfc568 --- /dev/null +++ b/svtools/inc/svtools/accessibletable.hxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * 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: accessibletable.hxx,v $ + * $Revision: 1.4 $ + * + * 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 _SVTOOLS_ACCESSIBLETABLE_HXX +#define _SVTOOLS_ACCESSIBLETABLE_HXX + +#include <vcl/window.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> + +// ============================================================================ + +namespace svt{ namespace table +{ + +typedef sal_Int32 RowPos; + +// ============================================================================ + +enum AccessibleTableType +{ + /** Child index of the column header bar (first row). */ + TCINDEX_COLUMNHEADERBAR = 0, + /** Child index of the row header bar ("handle column"). */ + TCINDEX_ROWHEADERBAR = 1, + /** Child index of the data table. */ + TCINDEX_TABLE = 2 +}; + +enum AccessibleTableControlObjType +{ + TCTYPE_GRIDCONTROL, /// The GridControl itself. + TCTYPE_TABLE, /// The data table. + TCTYPE_ROWHEADERBAR, /// The row header bar. + TCTYPE_COLUMNHEADERBAR, /// The horizontal column header bar. + TCTYPE_TABLECELL, /// A cell of the data table. + TCTYPE_ROWHEADERCELL, /// A cell of the row header bar. + TCTYPE_COLUMNHEADERCELL, /// A cell of the column header bar. +}; + +// ============================================================================ + +#define XACC ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + +/** This abstract class provides methods to implement an accessible table object. +*/ +class IAccessibleTable +{ +public: + /** @return The position of the current row. */ + virtual sal_Int32 GetCurrentRow() const = 0; + /** @return The position of the current column. */ + virtual sal_Int32 GetCurrentColumn() const = 0; + /** Creates and returns the accessible object of the whole GridControl. */ + virtual XACC CreateAccessible()= 0; + virtual XACC CreateAccessibleControl( sal_Int32 _nIndex )= 0; + virtual ::rtl::OUString GetAccessibleObjectName(AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const= 0; + virtual sal_Bool GoToCell( sal_Int32 _nColumnPos, sal_Int32 _nRow )= 0; + virtual sal_Bool HasColHeader() = 0; + virtual sal_Bool HasRowHeader() = 0; + + /** return the description of the specified object. + @param eObjType + The type to ask for + @param _nPosition + The position of a tablecell (index position), header bar colum/row cell + @return + The description of the specified object. + */ + virtual ::rtl::OUString GetAccessibleObjectDescription(AccessibleTableControlObjType eObjType, sal_Int32 _nPosition = -1) const= 0; + + /** Fills the StateSet with all states (except DEFUNC and SHOWING, done by + the accessible object), depending on the specified object type. */ + virtual void FillAccessibleStateSet( + ::utl::AccessibleStateSetHelper& rStateSet, + AccessibleTableControlObjType eObjType ) const= 0; + + // Window + virtual Rectangle GetWindowExtentsRelative( Window *pRelativeWindow ) = 0; + virtual void GrabFocus()= 0; + virtual XACC GetAccessible( BOOL bCreate = TRUE )= 0; + virtual Window* GetAccessibleParentWindow() const= 0; + virtual Window* GetWindowInstance()= 0; + virtual sal_Int32 GetAccessibleControlCount() const = 0; + virtual sal_Bool ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint )= 0; + virtual long GetRowCount() const= 0; + virtual long GetColumnCount() const= 0; + virtual sal_Bool HasRowHeader() const= 0; + virtual sal_Int32 GetSelectedRowCount() const= 0; + virtual bool IsRowSelected( long _nRow ) const= 0; + virtual sal_Bool ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint )= 0; + virtual Rectangle calcHeaderRect( sal_Bool _bIsColumnBar, BOOL _bOnScreen = TRUE ) = 0; + virtual Rectangle calcTableRect( BOOL _bOnScreen = TRUE ) = 0; + virtual Rectangle GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex)= 0; + virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)= 0; + virtual void FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const= 0; + virtual ::rtl::OUString GetRowDescription( sal_Int32 _nRow ) const = 0; + virtual ::rtl::OUString GetRowName(sal_Int32 _nIndex) const = 0; + virtual ::rtl::OUString GetColumnDescription( sal_uInt16 _nColumnPos ) const = 0; + virtual ::rtl::OUString GetColumnName( sal_Int32 _nIndex ) const = 0; + virtual ::rtl::OUString GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos) const = 0; + virtual std::vector<sal_Int32>& GetSelectedRows() = 0; +}; + +// ---------------------------------------------------------------------------- + +/** interface for an implementation of a table control's Accesible component +*/ +class IAccessibleTableControl +{ +public: + /** returns the XAccessible object itself + + The reference returned here can be used to control the life time of the + IAccessibleTableImplementation object. + + The returned reference is guaranteed to not be <NULL/>. + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + getMyself() = 0; + + /** disposes the accessible implementation, so that it becomes defunc + */ + virtual void dispose() = 0; + + /** checks whether the accessible implementation, and its context, are still alive + @return <TRUE/>, if the object is not disposed or disposing. + */ + virtual sal_Bool isAlive() const = 0; + + /** returns the accessible object for the row or the column header bar + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + getTableHeader( ::svt::table::AccessibleTableControlObjType _eObjType ) = 0; + + /** returns the accessible object for the table representation + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + getTable() = 0; + + ///** Commits an event to all listeners. */ + virtual void commitEvent( + sal_Int16 nEventId, + const ::com::sun::star::uno::Any& rNewValue, + const ::com::sun::star::uno::Any& rOldValue + ) = 0; +}; + +// ---------------------------------------------------------------------------- + +// ============================================================================ +} // namespace table +} // namespace svt + +// ============================================================================ + +#endif // _SVTOOLS_ACCESSIBLETABLE_HXX + diff --git a/svtools/inc/svtools/table/tablecontrol.hxx b/svtools/inc/svtools/table/tablecontrol.hxx index 98fddcb7d9e1..e3edd0b681ae 100644 --- a/svtools/inc/svtools/table/tablecontrol.hxx +++ b/svtools/inc/svtools/table/tablecontrol.hxx @@ -30,6 +30,8 @@ #include <vcl/ctrl.hxx> #include <vcl/seleng.hxx> #include <svtools/table/tabledatawindow.hxx> +#include <svtools/accessibletable.hxx> +#include "svtaccessiblefactory.hxx" //........................................................................ namespace svt { namespace table @@ -38,6 +40,8 @@ namespace svt { namespace table class TableControl_Impl; class TableDataWindow; + class AccessibleTableControl_Impl; + //==================================================================== //= TableControl //==================================================================== @@ -55,10 +59,11 @@ namespace svt { namespace table The control supports the concept of a <em>current</em> (or <em>active</em> cell). + The control supports accessibility, this is encapsulated in IAccessibleTable // TODO: scrolling? */ - class TableControl : public Control + class TableControl : public Control, public IAccessibleTable { private: DECL_LINK( ImplMouseButtonDownHdl, MouseEvent* ); @@ -66,6 +71,8 @@ namespace svt { namespace table TableControl_Impl* m_pImpl; public: + ::std::auto_ptr< AccessibleTableControl_Impl > m_pAccessTable; + TableControl( Window* _pParent, WinBits _nStyle ); ~TableControl(); @@ -88,11 +95,11 @@ namespace svt { namespace table if there is no active cell, e.g. because the table does not contain any rows or columns. */ - RowPos GetCurrentRow() const; + sal_Int32 GetCurrentRow() const; /** returns the row, which contains the input point*/ - RowPos GetCurrentRow (const Point& rPoint); + ColPos GetCurrentRow (const Point& rPoint); /** retrieves the current column @@ -103,7 +110,7 @@ namespace svt { namespace table if there is no active cell, e.g. because the table does not contain any rows or columns. */ - ColPos GetCurrentColumn() const; + sal_Int32 GetCurrentColumn() const; /** activates the cell at the given position @@ -113,7 +120,7 @@ namespace svt { namespace table or impossibility to execute the move at all (for instance because of invalid coordinates). */ - bool GoTo( ColPos _nColumn, RowPos _nRow ); + bool GoTo( ColPos _nColumnPos, RowPos _nRow); /** moves the active cell to the given column, by keeping the active row @@ -147,26 +154,91 @@ namespace svt { namespace table void InvalidateDataWindow(RowPos _nRowStart, bool _bRemoved); /**gets the vector, which contains the selected rows */ - std::vector<RowPos> getSelectedRows(); + std::vector<sal_Int32>& GetSelectedRows(); /**after removing a row, updates the vector which contains the selected rows if the row, which should be removed, is selected, it will be erased from the vector */ void removeSelectedRow(RowPos _nRowPos); SelectionEngine* getSelEngine(); TableDataWindow* getDataWindow(); - // protected: + // Window overridables virtual void GetFocus(); virtual void LoseFocus(); virtual void KeyInput( const KeyEvent& rKEvt ); //virtual long Notify(NotifyEvent& rNEvt); + /** Creates and returns the accessible object of the whole BrowseBox. */ + virtual XACC CreateAccessible(); + virtual XACC CreateAccessibleControl( sal_Int32 _nIndex ); + virtual ::rtl::OUString GetAccessibleObjectName(AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const; + virtual sal_Bool GoToCell( sal_Int32 _nColumnPos, sal_Int32 _nRow ); + virtual ::rtl::OUString GetAccessibleObjectDescription(AccessibleTableControlObjType eObjType, sal_Int32 _nPosition = -1) const; + virtual void FillAccessibleStateSet( + ::utl::AccessibleStateSetHelper& rStateSet, + AccessibleTableControlObjType eObjType ) const; + + //// Window + virtual Rectangle GetWindowExtentsRelative( Window *pRelativeWindow ); + virtual void GrabFocus(); + virtual XACC GetAccessible( BOOL bCreate = TRUE ); + virtual Window* GetAccessibleParentWindow() const; + virtual Window* GetWindowInstance(); + virtual sal_Int32 GetAccessibleControlCount() const; + virtual sal_Bool ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint ); + virtual long GetRowCount() const; + virtual long GetColumnCount() const; + virtual sal_Bool HasRowHeader() const; + virtual sal_Int32 GetSelectedRowCount() const; + virtual bool IsRowSelected( long _nRow ) const; + virtual sal_Bool ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint ); + virtual Rectangle calcHeaderRect( sal_Bool _bIsColumnBar, BOOL _bOnScreen = TRUE ); + virtual Rectangle calcTableRect( BOOL _bOnScreen = TRUE ); + virtual Rectangle GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex); + virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint); + virtual void FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const; + virtual ::rtl::OUString GetRowDescription( sal_Int32 _nRow ) const; + virtual ::rtl::OUString GetRowName(sal_Int32 _nIndex) const; + virtual ::rtl::OUString GetColumnDescription( sal_uInt16 _nColumnPos ) const; + virtual ::rtl::OUString GetColumnName( sal_Int32 _nIndex ) const; + virtual ::rtl::OUString GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos) const; + virtual sal_Bool HasRowHeader(); + virtual sal_Bool HasColHeader(); + virtual sal_Bool isAccessibleAlive( ) const; + virtual void commitGridControlEvent( sal_Int16 _nEventId, const com::sun::star::uno::Any& _rNewValue, const com::sun::star::uno::Any& _rOldValue ); + + + protected: + /// retrieves the XAccessible implementation associated with the GridControl instance + ::svt::IAccessibleFactory& getAccessibleFactory(); + private: TableControl(); // never implemented TableControl( const TableControl& ); // never implemented TableControl& operator=( const TableControl& ); // never implemented }; + class AccessibleTableControl_Impl + { + public: + AccessibleFactoryAccess m_aFactoryAccess; + IAccessibleTableControl* m_pAccessible; + + public: + AccessibleTableControl_Impl() : m_pAccessible(NULL) + { + } + + + /// @see AccessibleTableControl::getTableRowHeader + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + getAccessibleTableHeader( AccessibleTableControlObjType _eObjType ); + /// @see AccessibleTableControl::getTable + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + getAccessibleTable( ); + + }; + //........................................................................ } } // namespace svt::table //........................................................................ diff --git a/svtools/inc/svtools/table/tablemodel.hxx b/svtools/inc/svtools/table/tablemodel.hxx index a1af1e1750ed..6e74d35b8586 100644 --- a/svtools/inc/svtools/table/tablemodel.hxx +++ b/svtools/inc/svtools/table/tablemodel.hxx @@ -434,13 +434,13 @@ namespace svt { namespace table virtual void setCellContent(std::vector<std::vector<rtl::OUString> > cellContent)=0; /** gets the content of the cells */ - virtual std::vector<std::vector<rtl::OUString> > getCellContent() = 0; + virtual std::vector<std::vector<rtl::OUString> >& getCellContent() = 0; /**sets title of header rows */ virtual void setRowHeaderName(std::vector<rtl::OUString> cellColumnContent)=0; /** gets title of header rows */ - virtual std::vector<rtl::OUString> getRowHeaderName() = 0; + virtual std::vector<rtl::OUString>& getRowHeaderName() = 0; /// destroys the table model instance virtual ~ITableModel() { } diff --git a/svtools/prj/d.lst b/svtools/prj/d.lst index 3570ea9bf143..924459d9c9f0 100644 --- a/svtools/prj/d.lst +++ b/svtools/prj/d.lst @@ -81,6 +81,7 @@ mkdir: %_DEST%\inc%_EXT%\svtools ..\inc\svtools\accessibletableprovider.hxx %_DEST%\inc%_EXT%\svtools\accessibletableprovider.hxx ..\inc\svtools\AccessibleBrowseBoxObjType.hxx %_DEST%\inc%_EXT%\svtools\AccessibleBrowseBoxObjType.hxx ..\inc\svtools\accessiblefactory.hxx %_DEST%\inc%_EXT%\svtools\accessiblefactory.hxx +..\inc\svtools\accessibletable.hxx %_DEST%\inc%_EXT%\svtools\accessibletable.hxx ..\inc\svtools\textwindowpeer.hxx %_DEST%\inc%_EXT%\svtools\textwindowpeer.hxx ..\inc\imgdef.hxx %_DEST%\inc%_EXT%\svtools\imgdef.hxx ..\inc\inetdef.hxx %_DEST%\inc%_EXT%\svtools\inetdef.hxx @@ -313,6 +314,8 @@ mkdir: %_DEST%\inc%_EXT%\svtools ..\inc\textwindowaccessibility.hxx %_DEST%\inc%_EXT%\svtools\textwindowaccessibility.hxx +..\inc\docpasswdrequest.hxx %_DEST%\inc%_EXT%\svtools\docpasswdrequest.hxx +..\inc\docmspasswdrequest.hxx %_DEST%\inc%_EXT%\svtools\docmspasswdrequest.hxx ..\inc\fontsubstconfig.hxx %_DEST%\inc%_EXT%\svtools\fontsubstconfig.hxx ..\inc\apearcfg.hxx %_DEST%\inc%_EXT%\svtools\apearcfg.hxx ..\inc\fltrcfg.hxx %_DEST%\inc%_EXT%\svtools\fltrcfg.hxx diff --git a/svtools/source/misc/svtaccessiblefactory.cxx b/svtools/source/misc/svtaccessiblefactory.cxx index b2d57c250d32..a4b3cc1e8ecc 100644 --- a/svtools/source/misc/svtaccessiblefactory.cxx +++ b/svtools/source/misc/svtaccessiblefactory.cxx @@ -107,6 +107,15 @@ namespace svt return NULL; } + virtual table::IAccessibleTableControl* + createAccessibleTableControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_rxParent*/, + table::IAccessibleTable& /*_rTable*/ + ) const + { + return NULL; + } + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > createAccessibleIconChoiceCtrl( SvtIconChoiceCtrl& /*_rIconCtrl*/, diff --git a/svtools/source/table/tablecontrol.cxx b/svtools/source/table/tablecontrol.cxx index c8895a19408d..1d7b046ae94b 100644 --- a/svtools/source/table/tablecontrol.cxx +++ b/svtools/source/table/tablecontrol.cxx @@ -30,10 +30,35 @@ #include "tablegeometry.hxx" #include "tablecontrol_impl.hxx" #include "svtools/table/tabledatawindow.hxx" +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> + +using namespace ::com::sun::star::uno; +using ::com::sun::star::accessibility::XAccessible; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::lang; +using namespace utl; +//using namespace rtl; //........................................................................ namespace svt { namespace table { -//........................................................................ + //==================================================================== + //= AccessibleTableControl_Impl + //==================================================================== + // ---------------------------------------------------------------------------- + Reference< XAccessible > AccessibleTableControl_Impl::getAccessibleTableHeader( AccessibleTableControlObjType _eObjType ) + { + if ( m_pAccessible && m_pAccessible->isAlive() ) + return m_pAccessible->getTableHeader( _eObjType ); + return NULL; + } + // ---------------------------------------------------------------------------- + Reference< XAccessible > AccessibleTableControl_Impl::getAccessibleTable( ) + { + if ( m_pAccessible && m_pAccessible->isAlive() ) + return m_pAccessible->getTable( ); + return NULL; + } //==================================================================== //= TableControl @@ -45,12 +70,17 @@ namespace svt { namespace table { m_pImpl->getDataWindow()->SetMouseButtonDownHdl( LINK( this, TableControl, ImplMouseButtonDownHdl ) ); m_pImpl->getDataWindow()->SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) ); + m_pAccessTable.reset(new ::svt::table::AccessibleTableControl_Impl()); } //-------------------------------------------------------------------- TableControl::~TableControl() { DELETEZ( m_pImpl ); + if ( m_pAccessTable->m_pAccessible ) + { + m_pAccessTable->m_pAccessible->dispose(); + } } //-------------------------------------------------------------------- @@ -59,7 +89,7 @@ namespace svt { namespace table if ( !m_pImpl->getInputHandler()->GetFocus( *m_pImpl ) ) { Control::GetFocus(); - GrabFocus(); + Control::GrabFocus(); } } @@ -109,13 +139,13 @@ namespace svt { namespace table } //-------------------------------------------------------------------- - RowPos TableControl::GetCurrentRow() const + sal_Int32 TableControl::GetCurrentRow() const { return m_pImpl->getCurRow(); } //-------------------------------------------------------------------- - ColPos TableControl::GetCurrentColumn() const + sal_Int32 TableControl::GetCurrentColumn() const { return m_pImpl->getCurColumn(); } @@ -126,6 +156,11 @@ namespace svt { namespace table return m_pImpl->goTo( _nColumn, _nRow ); } //-------------------------------------------------------------------- + sal_Bool TableControl::GoToCell(sal_Int32 _nColPos, sal_Int32 _nRowPos) + { + return m_pImpl->goTo( _nColPos, _nRowPos ); + } + //-------------------------------------------------------------------- void TableControl::InvalidateDataWindow(RowPos _nRowStart, bool _bRemoved) { Rectangle _rRect; @@ -135,7 +170,7 @@ namespace svt { namespace table return m_pImpl->invalidateRow(_nRowStart, _rRect); } //-------------------------------------------------------------------- - std::vector<RowPos> TableControl::getSelectedRows() + std::vector<sal_Int32>& TableControl::GetSelectedRows() { return m_pImpl->getSelectedRows(); } @@ -174,6 +209,331 @@ namespace svt { namespace table { return m_pImpl->getDataWindow(); } + + Reference< XAccessible > TableControl::CreateAccessible() + { + Window* pParent = GetAccessibleParentWindow(); + DBG_ASSERT( pParent, "TableControl::CreateAccessible - parent not found" ); + + if( pParent && !m_pAccessTable->m_pAccessible) + { + Reference< XAccessible > xAccParent = pParent->GetAccessible(); + if( xAccParent.is() ) + { + m_pAccessTable->m_pAccessible = getAccessibleFactory().createAccessibleTableControl( + xAccParent, *this + ); + } + } + Reference< XAccessible > xAccessible; + if ( m_pAccessTable->m_pAccessible ) + xAccessible = m_pAccessTable->m_pAccessible->getMyself(); + return xAccessible; + } + Reference<XAccessible> TableControl::CreateAccessibleControl( sal_Int32 _nIndex ) + { + (void)_nIndex; + DBG_ASSERT( FALSE, "TableControl::CreateAccessibleControl: to be overwritten!" ); + return NULL; + } + ::rtl::OUString TableControl::GetAccessibleObjectName( AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const + { + ::rtl::OUString aRetText; + switch( eObjType ) + { + case TCTYPE_GRIDCONTROL: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridControl" ) ); + break; + case TCTYPE_TABLE: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Table" ) ); + break; + case TCTYPE_ROWHEADERBAR: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowHeaderBar" ) ); + break; + case TCTYPE_COLUMNHEADERBAR: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ColumnHeaderBar" ) ); + break; + case TCTYPE_TABLECELL: + aRetText = GetCellContent(_nRow, _nCol); + break; + case TCTYPE_ROWHEADERCELL: + aRetText = GetRowName(_nRow); + break; + case TCTYPE_COLUMNHEADERCELL: + aRetText = GetColumnName(_nCol); + break; + default: + OSL_ENSURE(0,"GridControl::GetAccessibleName: invalid enum!"); + } + return aRetText; + } +// ----------------------------------------------------------------------------- + +::rtl::OUString TableControl::GetAccessibleObjectDescription( AccessibleTableControlObjType eObjType, sal_Int32 ) const +{ + ::rtl::OUString aRetText; + switch( eObjType ) + { + case TCTYPE_GRIDCONTROL: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridControl description" ) ); + break; + case TCTYPE_TABLE: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLE description" ) ); + break; + case TCTYPE_ROWHEADERBAR: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERBAR description" ) ); + break; + case TCTYPE_COLUMNHEADERBAR: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERBAR description" ) ); + break; + case TCTYPE_TABLECELL: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLECELL description" ) ); + break; + case TCTYPE_ROWHEADERCELL: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERCELL description" ) ); + break; + case TCTYPE_COLUMNHEADERCELL: + aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERCELL description" ) ); + break; + } + return aRetText; +} +// ----------------------------------------------------------------------------- + +::rtl::OUString TableControl::GetRowDescription( sal_Int32 _nRow) const +{ + (void)_nRow; + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "row description" ) ); +} +// ----------------------------------------------------------------------------- + +::rtl::OUString TableControl::GetRowName( sal_Int32 _nIndex) const +{ + return GetModel()->getRowHeaderName()[_nIndex]; +} +// ----------------------------------------------------------------------------- + +::rtl::OUString TableControl::GetColumnDescription( sal_uInt16 _nColumn) const +{ + (void)_nColumn; + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "col description" ) ); +} +// ----------------------------------------------------------------------------- + +::rtl::OUString TableControl::GetColumnName( sal_Int32 _nIndex) const +{ + return GetModel()->getColumnModel(_nIndex)->getName(); +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString TableControl::GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos) const +{ + ::rtl::OUString cellContent = ::rtl::OUString::createFromAscii(""); + std::vector<std::vector<rtl::OUString> >& aTableContent = GetModel()->getCellContent(); + if(&aTableContent) + { + std::vector<rtl::OUString>& aRowContent = aTableContent[_nRowPos]; + if(&aRowContent) + cellContent = aRowContent[_nColPos]; + } + return cellContent; +} +// ----------------------------------------------------------------------------- + +void TableControl::FillAccessibleStateSet( + ::utl::AccessibleStateSetHelper& rStateSet, + AccessibleTableControlObjType eObjType ) const +{ + switch( eObjType ) + { + case TCTYPE_GRIDCONTROL: + case TCTYPE_TABLE: + + rStateSet.AddState( AccessibleStateType::FOCUSABLE ); + rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE); + if ( HasFocus() ) + rStateSet.AddState( AccessibleStateType::FOCUSED ); + if ( IsActive() ) + rStateSet.AddState( AccessibleStateType::ACTIVE ); + if ( IsEnabled() ) + rStateSet.AddState( AccessibleStateType::ENABLED ); + if ( IsReallyVisible() ) + rStateSet.AddState( AccessibleStateType::VISIBLE ); + rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS ); + + break; + case TCTYPE_ROWHEADERBAR: + rStateSet.AddState( AccessibleStateType::VISIBLE ); + rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS ); + break; + case TCTYPE_COLUMNHEADERBAR: + rStateSet.AddState( AccessibleStateType::VISIBLE ); + rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS ); + break; + case TCTYPE_TABLECELL: + { + //sal_Int32 nRow = GetCurRow(); + //sal_uInt16 nColumn = GetCurColumnId(); + //if ( IsFieldVisible(nRow,nColumn) ) + // rStateSet.AddState( AccessibleStateType::VISIBLE ); + rStateSet.AddState( AccessibleStateType::TRANSIENT ); + rStateSet.AddState( AccessibleStateType::SELECTABLE); + if( GetSelectedRowCount()>0) + rStateSet.AddState( AccessibleStateType::SELECTED); + } + break; + case TCTYPE_ROWHEADERCELL: + rStateSet.AddState( AccessibleStateType::VISIBLE ); + rStateSet.AddState( AccessibleStateType::TRANSIENT ); + break; + case TCTYPE_COLUMNHEADERCELL: + rStateSet.AddState( AccessibleStateType::VISIBLE ); + break; + } +} + +Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) +{ + return Control::GetWindowExtentsRelative( pRelativeWindow ); +} +//----------------------------------------------------------------------------- +void TableControl::GrabFocus() +{ + Control::GrabFocus(); +} +// ----------------------------------------------------------------------------- +Reference< XAccessible > TableControl::GetAccessible( BOOL bCreate ) +{ + return Control::GetAccessible( bCreate ); +} +// ----------------------------------------------------------------------------- +Window* TableControl::GetAccessibleParentWindow() const +{ + return Control::GetAccessibleParentWindow(); +} +// ----------------------------------------------------------------------------- +Window* TableControl::GetWindowInstance() +{ + return this; +} + +sal_Bool TableControl::HasRowHeader() +{ + return GetModel()->hasRowHeaders(); +} +//-------------------------------------------------------------------------------- +sal_Bool TableControl::HasColHeader() +{ + return GetModel()->hasColumnHeaders(); +} +//-------------------------------------------------------------------------------- +sal_Int32 TableControl::GetAccessibleControlCount() const +{ + sal_Int32 count = 0; + if(GetRowCount()>0) + count+=1; + if(GetModel()->hasRowHeaders()) + count+=1; + if(GetModel()->hasColumnHeaders()) + count+=1; + return count; +} +sal_Bool TableControl::ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint ) +{ + sal_Int32 nRow = m_pImpl->getCurrentRow(_rPoint); + sal_Int32 nCol = GetCurrentColumn(); + _rnIndex = nRow * GetColumnCount() + nCol; + return nRow>=0 ? sal_True : sal_False; +} + +long TableControl::GetRowCount() const +{ + return m_pImpl->getRowCount(); +} +long TableControl::GetColumnCount() const +{ + return m_pImpl->getColumnCount(); +} +sal_Bool TableControl::HasRowHeader() const +{ + PTableModel pModel = GetModel(); + return pModel->hasRowHeaders(); +} +sal_Int32 TableControl::GetSelectedRowCount() const +{ + return m_pImpl->getSelectedRows().size(); +} +bool TableControl::IsRowSelected( long _nRow ) const +{ + return m_pImpl->isRowSelected(m_pImpl->getSelectedRows(), _nRow); +} +sal_Bool TableControl::ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint ) +{ + _rnRow = m_pImpl->getCurrentRow(_rPoint); + _rnColPos = GetCurrentColumn(); + return _rnRow>=0 ? sal_True : sal_False; +} +void TableControl::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const +{ + if ( GetCurrentRow() == _nRow && GetCurrentColumn() == _nColumnPos ) + _rStateSet.AddState( AccessibleStateType::FOCUSED ); + else // only transient when column is not focused + _rStateSet.AddState( AccessibleStateType::TRANSIENT ); +} +Rectangle TableControl::GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex) +{ + (void)_nRow; + (void)_nColumnPos; + return GetCharacterBounds(nIndex); +} +sal_Int32 TableControl::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint) +{ + (void)_nRow; + (void)_nColumnPos; + return GetIndexForPoint(_rPoint);
+; +} + // -----------------------------------------------------------------------------
+sal_Bool TableControl::isAccessibleAlive( ) const
+{
+ return ( NULL != m_pAccessTable->m_pAccessible ) && m_pAccessTable->m_pAccessible->isAlive();
+}
+ +// ----------------------------------------------------------------------------- +::svt::IAccessibleFactory& TableControl::getAccessibleFactory() +{ + return m_pAccessTable->m_aFactoryAccess.getFactory(); +} +// -----------------------------------------------------------------------------
+void TableControl::commitGridControlEvent( sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
+{
+ if ( isAccessibleAlive() )
+ m_pAccessTable->m_pAccessible->commitEvent( _nEventId, _rNewValue, _rOldValue);
+} +// -----------------------------------------------------------------------------
+Rectangle TableControl::calcHeaderRect(sal_Bool _bIsColumnBar,BOOL _bOnScreen)
+{
+ (void)_bOnScreen;
+ Rectangle aRectTable, aRectTableWithHeaders;
+ m_pImpl->impl_getAllVisibleDataCellArea(aRectTable);
+ m_pImpl->impl_getAllVisibleCellsArea(aRectTableWithHeaders);
+ Size aSizeTable(aRectTable.GetSize());
+ Size aSizeTableWithHeaders(aRectTableWithHeaders.GetSize());
+ if(_bIsColumnBar)
+ return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width()-aSizeTable.Width(), aSizeTableWithHeaders.Height()));
+ else
+ return Rectangle(aRectTableWithHeaders.TopLeft(),Size(aSizeTableWithHeaders.Width(), aSizeTableWithHeaders.Height()-aSizeTable.Height()));
+}
+// -----------------------------------------------------------------------------
+Rectangle TableControl::calcTableRect(BOOL _bOnScreen)
+{
+ (void)_bOnScreen;
+ Rectangle aRect;
+ m_pImpl->impl_getAllVisibleDataCellArea(aRect);
+ return aRect;
+}
+ //........................................................................ -} } // namespace svt::table +}} // namespace svt::table //........................................................................ diff --git a/svtools/source/table/tablecontrol_impl.cxx b/svtools/source/table/tablecontrol_impl.cxx index e1ff3aeb7f2a..89c0eed4229a 100644 --- a/svtools/source/table/tablecontrol_impl.cxx +++ b/svtools/source/table/tablecontrol_impl.cxx @@ -181,24 +181,23 @@ namespace svt { namespace table { (void)pCellEntryType; } - virtual std::vector<std::vector<rtl::OUString> > getCellContent() + virtual std::vector<std::vector<rtl::OUString> >& getCellContent() { - std::vector<rtl::OUString> cCC; - cCC.push_back(rtl::OUString::createFromAscii("")); - std::vector<std::vector<rtl::OUString> > cC; - cC.push_back(cCC); - return cC; + return *( new std::vector<std::vector<rtl::OUString> >); } virtual void setRowHeaderName(std::vector<rtl::OUString> pCellEntryType) { (void)pCellEntryType; } - virtual std::vector<rtl::OUString> getRowHeaderName() + virtual std::vector<rtl::OUString>& getRowHeaderName() { - std::vector<rtl::OUString> cCC; - cCC.push_back(rtl::OUString::createFromAscii("")); - return cCC; + aRowHeaderNames.clear(); + aRowHeaderNames.push_back(rtl::OUString::createFromAscii("")); + return aRowHeaderNames; } + + private: + std::vector<rtl::OUString> aRowHeaderNames; }; @@ -882,7 +881,7 @@ namespace svt { namespace table impl_getAllVisibleDataCellArea( aAllDataCellsArea ); //get the vector, which contains row vectors, each containing the data for the cells in this row - std::vector<std::vector<rtl::OUString> > aCellContent = m_pModel->getCellContent(); + std::vector<std::vector<rtl::OUString> >& aCellContent = m_pModel->getCellContent(); //if the vector is empty, fill it with empty data, so the table can be painted if(aCellContent.empty()) { @@ -895,7 +894,7 @@ namespace svt { namespace table } std::vector<std::vector<rtl::OUString> >::iterator it = aCellContent.begin()+m_nTopRow; //get the vector, which contains the row header titles - std::vector<rtl::OUString> aRowHeaderContent; + std::vector<rtl::OUString>& aRowHeaderContent = m_pModel->getRowHeaderName(); ::std::vector<rtl::OUString>::iterator itRowName = aRowHeaderContent.begin(); if(m_pModel->hasRowHeaders()) @@ -1525,7 +1524,7 @@ namespace svt { namespace table } //------------------------------------------------------------------------------- - std::vector<RowPos> TableControl_Impl::getSelectedRows() + std::vector<RowPos>& TableControl_Impl::getSelectedRows() { return m_nRowSelected; } diff --git a/svtools/source/table/tablecontrol_impl.hxx b/svtools/source/table/tablecontrol_impl.hxx index 410bc8b4c3a1..0a25e82e4502 100644 --- a/svtools/source/table/tablecontrol_impl.hxx +++ b/svtools/source/table/tablecontrol_impl.hxx @@ -138,6 +138,8 @@ namespace svt { namespace table inline RowPos getCurRow() const { return m_nCurRow; } inline void setCurRow(RowPos curRow){ m_nCurRow = curRow; } inline RowPos getTopRow() const { return m_nTopRow; } + inline long getRowCount() const { return m_nRowCount; } + inline long getColumnCount() const { return m_nColumnCount; } inline long getColHeaderHightPixel() const { return m_nColHeaderHeightPixel; } @@ -194,7 +196,7 @@ namespace svt { namespace table /** to be called when a new row is added to the control*/ void invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect ); /** returns the vector, which contains the selected rows*/ - std::vector<RowPos> getSelectedRows(); + std::vector<RowPos>& getSelectedRows(); /** updates the vector, which contains the selected rows after removing the row nRowPos*/ void removeSelectedRow(RowPos _nRowPos); void invalidateRows(RowPos _nRowStart, Rectangle& _rCellRect ); @@ -208,15 +210,6 @@ namespace svt { namespace table virtual SelectionEngine* getSelEngine(); TableDataWindow* getDataWindow(); - - private: - /** toggles the cursor visibility - - The method is not bound to the classes public invariants, as it's used in - situations where the they must not necessarily be fullfilled. - */ - void impl_ni_doSwitchCursor( bool _bOn ); - /** retrieves the area occupied by the totality of (at least partially) visible cells The returned area includes row and column headers. Also, it takes into @@ -234,6 +227,13 @@ namespace svt { namespace table minus the row and column header areas. */ void impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const; + private: + /** toggles the cursor visibility + + The method is not bound to the classes public invariants, as it's used in + situations where the they must not necessarily be fullfilled. + */ + void impl_ni_doSwitchCursor( bool _bOn ); /** returns the number of visible rows. diff --git a/svtools/source/uno/makefile.mk b/svtools/source/uno/makefile.mk index d8438bd48ccf..7b992637e152 100644 --- a/svtools/source/uno/makefile.mk +++ b/svtools/source/uno/makefile.mk @@ -58,7 +58,8 @@ SLOFILES= \ $(SLO)$/unocontroltablemodel.obj \ $(SLO)$/unoevent.obj \ $(SLO)$/unoiface.obj \ - $(SLO)$/unoimap.obj + $(SLO)$/unoimap.obj \ + $(SLO)$/svtxgridcontrol.obj # --- Targets ------------------------------------------------------ diff --git a/svtools/source/uno/svtxgridcontrol.cxx b/svtools/source/uno/svtxgridcontrol.cxx new file mode 100755 index 000000000000..2f2c896ee6a8 --- /dev/null +++ b/svtools/source/uno/svtxgridcontrol.cxx @@ -0,0 +1,458 @@ +/************************************************************************* + * + * 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: SVTXGridControl.cxx,v $ + * $Revision: 1.32 $ + * + * 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. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include "svtxgridcontrol.hxx" +#include <com/sun/star/view/SelectionType.hpp> +#include "svtools/table/gridtablerenderer.hxx" +#include "svtools/table/defaultinputhandler.hxx" +#include "svtools/table/tablecontrol.hxx" +#include "unocontroltablemodel.hxx" +#include <comphelper/sequence.hxx> +#include <rtl/ref.hxx> +#include <tools/debug.hxx> +#include <toolkit/helper/property.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/awt/grid/XGridColumn.hpp> +#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+ + +using ::rtl::OUString; +using namespace ::svt::table; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt::grid; +using namespace ::com::sun::star::view; +using namespace ::toolkit; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::accessibility::AccessibleEventId;
+using namespace ::com::sun::star::accessibility::AccessibleTableModelChangeType;
+using ::com::sun::star::accessibility::AccessibleTableModelChange;
+ + +SVTXGridControl::SVTXGridControl() + :m_pTableModel (new UnoControlTableModel()), + m_xDataModel(0), + m_xColumnModel(0), + m_bHasColumnHeaders(false), + m_bHasRowHeaders(false), + m_bVScroll(false), + m_bHScroll(false) +{ +} + +//-------------------------------------------------------------------- +SVTXGridControl::~SVTXGridControl() +{ + DELETEZ(m_pTableModel); +} + +::com::sun::star::uno::Any SVTXGridControl::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) +{ + ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType, + SAL_STATIC_CAST( ::com::sun::star::awt::grid::XGridControl*, this ), + SAL_STATIC_CAST( ::com::sun::star::awt::grid::XGridDataListener*, this ), + SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) ); + return (aRet.hasValue() ? aRet : VCLXWindow::queryInterface( rType )); +} + +// ::com::sun::star::lang::XTypeProvider +IMPL_XTYPEPROVIDER_START( SVTXGridControl ) + getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridControl>* ) NULL ), + getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel>* ) NULL ), + getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener>* ) NULL ), + VCLXWindow::getTypes() +IMPL_XTYPEPROVIDER_END + +::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel > SAL_CALL SVTXGridControl::getColumnModel( ) throw (::com::sun::star::uno::RuntimeException) +{ + return NULL; +} +void SAL_CALL SVTXGridControl::setColumnModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >& model ) throw (::com::sun::star::uno::RuntimeException) +{ + (void)model; +} +::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel > SAL_CALL SVTXGridControl::getDataModel( ) throw (::com::sun::star::uno::RuntimeException) +{ + return NULL; +} +void SAL_CALL SVTXGridControl::setDataModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >& model ) throw (::com::sun::star::uno::RuntimeException) +{ + (void)model; +} +sal_Int32 SAL_CALL SVTXGridControl::getItemIndexAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException) +{ + TableControl* pTable = (TableControl*)GetWindow(); + return pTable->GetCurrentRow( Point(x,y) ); +} + +void SAL_CALL SVTXGridControl::addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException) +{ + (void)listener; +} + +void SAL_CALL SVTXGridControl::removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException) +{ + (void) listener; +} + +void SVTXGridControl::setProperty( const ::rtl::OUString& PropertyName, const Any& aValue) throw(RuntimeException) +{ + ::vos::OGuard aGuard( GetMutex() ); + + TableControl* pTable = (TableControl*)GetWindow(); + + switch( GetPropertyId( PropertyName ) ) + { + case BASEPROPERTY_GRID_SELECTIONMODE: + { + SelectionType eSelectionType; + if( aValue >>= eSelectionType ) + { + SelectionMode eSelMode; + switch( eSelectionType ) + { + case SelectionType_SINGLE: eSelMode = SINGLE_SELECTION; break; + case SelectionType_RANGE: eSelMode = RANGE_SELECTION; break; + case SelectionType_MULTI: eSelMode = MULTIPLE_SELECTION; break; + // case SelectionType_NONE: + default: eSelMode = NO_SELECTION; break; + } + if( pTable->getSelEngine()->GetSelectionMode() != eSelMode ) + pTable->getSelEngine()->SetSelectionMode( eSelMode ); + } + break; + } + case BASEPROPERTY_HSCROLL: + { + sal_Bool bHScroll = true; + if( aValue >>= bHScroll ) + { + m_bHScroll = bHScroll; + } + break; + } + case BASEPROPERTY_VSCROLL: + { + sal_Bool bVScroll = true; + if( aValue >>= bVScroll ) + { + m_bVScroll = bVScroll; + } + break; + } + case BASEPROPERTY_GRID_SHOWROWHEADER: + { + sal_Bool rowHeader = true; + if( aValue >>= rowHeader ) + { + m_pTableModel->setRowHeaders(rowHeader); + } + break; + } + + case BASEPROPERTY_GRID_SHOWCOLUMNHEADER: + { + sal_Bool colHeader = true; + if( aValue >>= colHeader ) + { + m_pTableModel->setColumnHeaders(colHeader); + } + break; + } + case BASEPROPERTY_GRID_DATAMODEL: + { + m_xDataModel = Reference< XGridDataModel >( aValue, UNO_QUERY ); + Sequence<Sequence< ::rtl::OUString > > cellData = m_xDataModel->getData(); + Sequence<rtl::OUString> rowData(0); + std::vector< std::vector< rtl::OUString > > aCellContent(0); + for(int i = 0; i< m_xDataModel->getRowCount();++i) + { + rowData = cellData[i]; + std::vector<rtl::OUString> newRow( + comphelper::sequenceToContainer< std::vector<rtl::OUString > >(rowData)); + if(newRow.size() < (unsigned)m_pTableModel->getColumnCount()) + newRow.resize( m_pTableModel->getColumnCount(),rtl::OUString::createFromAscii("")); + aCellContent.push_back(newRow); + } + m_pTableModel->setCellContent(aCellContent); + Sequence< ::rtl::OUString > rowHeaders = m_xDataModel->getRowHeaders(); + std::vector< rtl::OUString > newRow( + comphelper::sequenceToContainer< std::vector<rtl::OUString > >(rowHeaders)); + m_pTableModel->setRowCount(m_xDataModel->getRowCount()); + m_pTableModel->setRowHeaderName(newRow); + break; + } + case BASEPROPERTY_GRID_COLUMNMODEL: + { + m_xColumnModel = Reference< XGridColumnModel >( aValue, UNO_QUERY ); + Sequence<Reference< XGridColumn > > columns = m_xColumnModel->getColumns(); + std::vector<Reference< XGridColumn > > aNewColumns( + comphelper::sequenceToContainer<std::vector<Reference< XGridColumn > > >(columns)); + /* if(m_pTable->GetColumnCount().size()>0) + m_pTable->GetColumnName.clear();*/ + for ( ::svt::table::ColPos col = 0; col < m_xColumnModel->getColumnCount(); ++col ) + { + UnoControlTableColumn* tableColumn = new UnoControlTableColumn(aNewColumns[col]); + m_pTableModel->getColumnModel().push_back((PColumnModel)tableColumn); + } + break; + } + default: + VCLXWindow::setProperty( PropertyName, aValue ); + break; + } +} + +Any SVTXGridControl::getProperty( const ::rtl::OUString& PropertyName ) throw(RuntimeException) +{ + ::vos::OGuard aGuard( GetMutex() ); + + const sal_uInt16 nPropId = GetPropertyId( PropertyName ); + TableControl* pTable = (TableControl*)GetWindow(); + if(pTable) + { + switch(nPropId) + { + case BASEPROPERTY_GRID_SELECTIONMODE: + { + SelectionType eSelectionType; + + SelectionMode eSelMode = pTable->getSelEngine()->GetSelectionMode(); + switch( eSelMode ) + { + case SINGLE_SELECTION: eSelectionType = SelectionType_SINGLE; break; + case RANGE_SELECTION: eSelectionType = SelectionType_RANGE; break; + case MULTIPLE_SELECTION:eSelectionType = SelectionType_MULTI; break; +// case NO_SELECTION: + default: eSelectionType = SelectionType_NONE; break; + } + return Any( eSelectionType ); + } + case BASEPROPERTY_GRID_SHOWROWHEADER: + { + return Any ((sal_Bool) m_pTableModel->hasRowHeaders()); + } + case BASEPROPERTY_GRID_SHOWCOLUMNHEADER: + return Any ((sal_Bool) m_pTableModel->hasColumnHeaders()); + case BASEPROPERTY_GRID_DATAMODEL: + return Any ( m_xDataModel ); + case BASEPROPERTY_GRID_COLUMNMODEL: + return Any ( m_xColumnModel); + case BASEPROPERTY_HSCROLL: + return Any ( m_bHScroll); + case BASEPROPERTY_VSCROLL: + return Any ( m_bVScroll); + } + } + return VCLXWindow::getProperty( PropertyName ); +} + +void SVTXGridControl::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds ) +{ + PushPropertyIds( rIds, + BASEPROPERTY_GRID_SHOWROWHEADER, + BASEPROPERTY_GRID_SHOWCOLUMNHEADER, + BASEPROPERTY_GRID_DATAMODEL, + BASEPROPERTY_GRID_COLUMNMODEL, + BASEPROPERTY_GRID_SELECTIONMODE, + 0); + VCLXWindow::ImplGetPropertyIds( rIds, true ); +} +void SAL_CALL SVTXGridControl::setVisible( sal_Bool bVisible ) throw(::com::sun::star::uno::RuntimeException) +{ + TableControl* pTable = (TableControl*)GetWindow(); + if ( pTable ) + { + pTable->SetModel(PTableModel(m_pTableModel)); + //m_pTable->SetPosSizePixel( Point( nPosX, nPosY ), Size(nWidth, nHeight) ); + pTable->Show( bVisible ); + } +} +void SAL_CALL SVTXGridControl::setFocus() throw(::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( GetMutex() ); + if ( GetWindow()) + GetWindow()->GrabFocus(); +} +void SAL_CALL SVTXGridControl::rowAdded(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + std::vector<OUString> aNewRow( + comphelper::sequenceToContainer< std::vector<rtl::OUString > >(Event.rowData)); + if(aNewRow.size()< (unsigned)m_pTableModel->getColumnCount()) + aNewRow.resize(m_pTableModel->getColumnCount(),rtl::OUString::createFromAscii("")); + m_pTableModel->getCellContent().push_back(aNewRow); + if(m_pTableModel->hasRowHeaders()) + m_pTableModel->getRowHeaderName().push_back(Event.headerName); + m_pTableModel->setRowCount(m_pTableModel->getRowHeaderName().size()); + TableControl* pTable = (TableControl*)GetWindow(); + pTable->InvalidateDataWindow(m_pTableModel->getRowHeaderName().size()-1, false); + //pTable->GrabFocus(); + if(pTable->isAccessibleAlive()) + { + pTable->commitGridControlEvent(TABLE_MODEL_CHANGED,
+ makeAny( AccessibleTableModelChange(INSERT, m_pTableModel->getRowCount()-1, m_pTableModel->getRowCount(), 0, m_pTableModel->getColumnCount())),
+ Any());
+ pTable->commitGridControlEvent(CHILD,
+ makeAny( pTable->m_pAccessTable->m_pAccessible->getTableHeader(TCTYPE_ROWHEADERBAR)),
+ Any());
+ for (sal_Int32 i = 0 ; i <= m_pTableModel->getColumnCount() ; ++i) + { + pTable->commitGridControlEvent( + CHILD, + makeAny( pTable->m_pAccessTable->m_pAccessible->getTable() ), + Any()); + }
+ } +} + +void SAL_CALL SVTXGridControl::rowRemoved(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + TableControl* pTable = (TableControl*)GetWindow(); + //unsigned int rows =m_pImpl->aCellContent.size()-1; + if(Event.index == -1) + { + if(m_pTableModel->hasRowHeaders()) + m_pTableModel->getRowHeaderName().clear(); + m_pTableModel->getCellContent().clear(); + if(pTable->isAccessibleAlive()) + { + pTable->commitGridControlEvent(TABLE_MODEL_CHANGED,
+ makeAny( AccessibleTableModelChange(DELETE, 0, m_pTableModel->getColumnCount(), 0, m_pTableModel->getColumnCount())),
+ Any());
+ } + } + else + { + pTable->removeSelectedRow(Event.index); + if(m_pTableModel->getCellContent().size()>1) + { + if(m_pTableModel->hasRowHeaders()) + m_pTableModel->getRowHeaderName().erase(m_pTableModel->getRowHeaderName().begin()+Event.index); + m_pTableModel->getCellContent().erase(m_pTableModel->getCellContent().begin()+Event.index); + + } + else + { + if(m_pTableModel->hasRowHeaders()) + m_pTableModel->getRowHeaderName().clear(); + m_pTableModel->getCellContent().clear(); + //m_pImpl->nRowCount=0; + } + } + //pTable->InvalidateDataWindow(Event.index, true); + m_pTableModel->setRowCount(m_pTableModel->getCellContent().size()); + pTable->InvalidateDataWindow(Event.index, true); + if(pTable->isAccessibleAlive()) + { + pTable->commitGridControlEvent(TABLE_MODEL_CHANGED,
+ makeAny( AccessibleTableModelChange(DELETE, Event.index, Event.index+1, 0, m_pTableModel->getColumnCount())),
+ Any());
+ //pTable->commitGridControlEvent(CHILD,
+ // makeAny( pTable->m_pAccessTable->m_pAccessible->getTableHeader(TCTYPE_ROWHEADERBAR)),
+ // Any());
+ //for (sal_Int32 i = 0 ; i <= m_pTableModel->getColumnCount() ; ++i) + //{ + // pTable->commitGridControlEvent( + // CHILD, + // makeAny( pTable->m_pAccessTable->m_pAccessible->getTable() ), + // Any()); + //}
+ } + //pTable->Invalidate(); +} + +void SAL_CALL SVTXGridControl::dataChanged(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + (void) Event; +} + + void SAL_CALL SVTXGridControl::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException) + { + VCLXWindow::disposing( Source ); + } + +::sal_Int32 SAL_CALL SVTXGridControl::getMinSelectionIndex() throw (::com::sun::star::uno::RuntimeException) +{ + return 0; +} + +::sal_Int32 SAL_CALL SVTXGridControl::getMaxSelectionIndex() throw (::com::sun::star::uno::RuntimeException) +{ + return 0; +} + +void SAL_CALL SVTXGridControl::insertIndexIntervall(::sal_Int32 start, ::sal_Int32 length) throw (::com::sun::star::uno::RuntimeException) +{ + (void)length; + (void)start; +} + +void SAL_CALL SVTXGridControl::removeIndexIntervall(::sal_Int32 start, ::sal_Int32 end) throw (::com::sun::star::uno::RuntimeException) +{ + (void)end; + (void)start; +} + +::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL SVTXGridControl::getSelection() throw (::com::sun::star::uno::RuntimeException) +{ + TableControl* pTable = (TableControl*)GetWindow(); + std::vector<RowPos>& selectedRows = pTable->GetSelectedRows(); + Sequence<sal_Int32> selectedRowsToSequence(comphelper::containerToSequence(selectedRows)); + return selectedRowsToSequence; +} + +::sal_Bool SAL_CALL SVTXGridControl::isCellEditable() throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL SVTXGridControl::isSelectionEmpty() throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL SVTXGridControl::isSelectedIndex(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException) +{ + (void)index; + return sal_False; +} + +void SAL_CALL SVTXGridControl::selectRow(::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException) +{ + (void)y; +} + +void SAL_CALL SVTXGridControl::selectColumn(::sal_Int32 x) throw (::com::sun::star::uno::RuntimeException) +{ + (void)x; +} diff --git a/svtools/source/uno/svtxgridcontrol.hxx b/svtools/source/uno/svtxgridcontrol.hxx new file mode 100755 index 000000000000..9ca6901681c9 --- /dev/null +++ b/svtools/source/uno/svtxgridcontrol.hxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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: SVTXGridControl.hxx,v $ + * $Revision: 1.32 $ + * + * 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 _SVT_GRIDCONTROL_HXX_ +#define _SVT_GRIDCONTROL_HXX_ + +#include <unocontroltablemodel.hxx> +#include <svtools/table/tablecontrol.hxx> +#include <com/sun/star/awt/grid/XGridControl.hpp> +#include <com/sun/star/awt/grid/XGridDataListener.hpp> +#include <com/sun/star/awt/grid/GridDataEvent.hpp> +#include <com/sun/star/awt/grid/XGridColumnModel.hpp> +#include <com/sun/star/awt/grid/XGridDataModel.hpp> +#include <com/sun/star/awt/grid/XGridSelectionListener.hpp> +#include <toolkit/awt/vclxwindow.hxx> +#include <toolkit/awt/vclxwindows.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/implbase2.hxx> +//#include <toolkit/helper/listenermultiplexer.hxx> + + +using namespace ::svt::table; + +class SVTXGridControl : public ::cppu::ImplInheritanceHelper2< VCLXWindow, ::com::sun::star::awt::grid::XGridControl, + ::com::sun::star::awt::grid::XGridDataListener> +{ +private: + UnoControlTableModel* m_pTableModel; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >m_xDataModel; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >m_xColumnModel; + bool m_bHasColumnHeaders; + bool m_bHasRowHeaders; + bool m_bVScroll; + bool m_bHScroll; + +public: + SVTXGridControl(); + ~SVTXGridControl(); + //XGridDataListener overridables + virtual void SAL_CALL rowAdded(const ::com::sun::star::awt::grid::GridDataEvent& Event) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowRemoved(const ::com::sun::star::awt::grid::GridDataEvent & Event) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL dataChanged(const ::com::sun::star::awt::grid::GridDataEvent & Event) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL acquire() throw() { VCLXWindow::acquire(); } + void SAL_CALL release() throw() { VCLXWindow::release(); } + + // ::com::sun::star::lang::XTypeProvider + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); + + //::com::sun::star::awt::grid::XGridControl + ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel > SAL_CALL getColumnModel( ) throw (::com::sun::star::uno::RuntimeException); + void SAL_CALL setColumnModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >& model ) throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel > SAL_CALL getDataModel( ) throw (::com::sun::star::uno::RuntimeException); + void SAL_CALL setDataModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >& model ) throw (::com::sun::star::uno::RuntimeException); + + virtual ::sal_Int32 SAL_CALL getMinSelectionIndex() throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getMaxSelectionIndex() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertIndexIntervall(::sal_Int32 start, ::sal_Int32 length) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeIndexIntervall(::sal_Int32 start, ::sal_Int32 end) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL getSelection() throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isCellEditable() throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isSelectionEmpty() throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isSelectedIndex(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectRow(::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectColumn(::sal_Int32 x) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getItemIndexAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException); + + void SAL_CALL setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value ) throw(::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Any SAL_CALL getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException); + static void ImplGetPropertyIds( std::list< sal_uInt16 > &aIds ); + void SAL_CALL setVisible(sal_Bool bVisible) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL setFocus() throw(::com::sun::star::uno::RuntimeException); + }; + #endif // _SVT_GRIDCONTROL_HXX_ diff --git a/svtools/source/uno/unocontroltablemodel.cxx b/svtools/source/uno/unocontroltablemodel.cxx index e322dbb8f96e..b4ddc2cc472d 100644 --- a/svtools/source/uno/unocontroltablemodel.cxx +++ b/svtools/source/uno/unocontroltablemodel.cxx @@ -47,38 +47,6 @@ using namespace ::svt::table; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::awt::grid; -using namespace ::svt::table; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::view; -using namespace ::toolkit; - -class UnoControlTableColumn : public IColumnModel - { - private: - ColumnID m_nID; - String m_sName; - bool m_bIsResizable; - TableMetrics m_nWidth; - TableMetrics m_nMinWidth; - TableMetrics m_nMaxWidth; - - public: - UnoControlTableColumn(Reference<XGridColumn>); - - // IColumnModel overridables - virtual ColumnID getID() const; - virtual bool setID( const ColumnID _nID ); - virtual String getName() const; - virtual void setName( const String& _rName ); - virtual bool isResizable() const; - virtual void setResizable( bool _bResizable ); - virtual TableMetrics getWidth() const; - virtual void setWidth( TableMetrics _nWidth ); - virtual TableMetrics getMinWidth() const; - virtual void setMinWidth( TableMetrics _nMinWidth ); - virtual TableMetrics getMaxWidth() const; - virtual void setMaxWidth( TableMetrics _nMaxWidth ); - }; //-------------------------------------------------------------------- UnoControlTableColumn::UnoControlTableColumn(Reference<XGridColumn> m_xGridColumn) @@ -181,7 +149,7 @@ class UnoControlTableColumn : public IColumnModel //==================================================================== struct UnoControlTableModel_Impl { - ::std::vector< PColumnModel > aColumns; + ::std::vector< PColumnModel >& aColumns; TableSize nRowCount; bool bHasColumnHeaders; bool bHasRowHeaders; @@ -190,11 +158,12 @@ class UnoControlTableColumn : public IColumnModel TableMetrics nRowHeight; TableMetrics nColumnHeaderHeight; TableMetrics nRowHeaderWidth; - std::vector<rtl::OUString> aRowHeadersTitle; - std::vector<std::vector<rtl::OUString> > aCellContent; + std::vector<rtl::OUString>& aRowHeadersTitle; + std::vector<std::vector<rtl::OUString> >& aCellContent; UnoControlTableModel_Impl() - :nRowCount ( 0 ) + :aColumns ( *(new std::vector< PColumnModel> (0))) + ,nRowCount ( 0 ) ,bHasColumnHeaders ( false ) ,bHasRowHeaders ( false ) ,pRenderer ( ) @@ -202,8 +171,8 @@ class UnoControlTableColumn : public IColumnModel ,nRowHeight ( 4 * 100 ) // 40 mm ,nColumnHeaderHeight( 5 * 100 ) // 50 mm ,nRowHeaderWidth ( 10 * 100 ) // 50 mm - ,aRowHeadersTitle ( 0 ) - ,aCellContent ( 0 ) + ,aRowHeadersTitle ( *(new std::vector<rtl::OUString>(0))) + ,aCellContent ( *(new std::vector<std::vector<OUString> >(0))) { } }; @@ -213,16 +182,10 @@ class UnoControlTableColumn : public IColumnModel //==================================================================== //-------------------------------------------------------------------- UnoControlTableModel::UnoControlTableModel() - :m_pImpl( new UnoControlTableModel_Impl ), - m_xDataModel(0), - m_xColumnModel(0), - m_bHasColumnHeaders(false), - m_bHasRowHeaders(false), - m_bVScroll(false), - m_bHScroll(false) - { - m_pImpl->bHasColumnHeaders = m_bHasColumnHeaders; - m_pImpl->bHasRowHeaders = m_bHasRowHeaders; + :m_pImpl( new UnoControlTableModel_Impl ) + { + m_pImpl->bHasColumnHeaders = false; + m_pImpl->bHasRowHeaders = false; m_pImpl->pRenderer.reset( new GridTableRenderer( *this ) ); m_pImpl->pInputHandler.reset( new DefaultInputHandler ); } @@ -236,7 +199,7 @@ class UnoControlTableColumn : public IColumnModel //-------------------------------------------------------------------- TableSize UnoControlTableModel::getColumnCount() const { - m_pImpl->aColumns.resize( m_xColumnModel->getColumnCount()); + //m_pImpl->aColumns.resize( m_xColumnModel->getColumnCount()); return (TableSize)m_pImpl->aColumns.size(); } @@ -312,6 +275,11 @@ class UnoControlTableColumn : public IColumnModel } //-------------------------------------------------------------------- + std::vector<PColumnModel>& UnoControlTableModel::getColumnModel() + { + return m_pImpl->aColumns; + } + //-------------------------------------------------------------------- PColumnModel UnoControlTableModel::getColumnModelByID( ColumnID id ) { (void)id; @@ -376,7 +344,7 @@ class UnoControlTableColumn : public IColumnModel //-------------------------------------------------------------------- ScrollbarVisibility UnoControlTableModel::getVerticalScrollbarVisibility(int overAllHeight, int actHeight) const { - if(overAllHeight>=actHeight && !m_bVScroll) + if(overAllHeight>=actHeight)// && !m_bVScroll) return ScrollbarShowNever; else return ScrollbarShowAlways; @@ -385,7 +353,7 @@ class UnoControlTableColumn : public IColumnModel //-------------------------------------------------------------------- ScrollbarVisibility UnoControlTableModel::getHorizontalScrollbarVisibility(int overAllWidth, int actWidth) const { - if(overAllWidth>=actWidth && !m_bHScroll) + if(overAllWidth>=actWidth)// && !m_bHScroll) return ScrollbarShowNever; else return ScrollbarShowAlways; @@ -393,25 +361,26 @@ class UnoControlTableColumn : public IColumnModel //-------------------------------------------------------------------- void UnoControlTableModel::setCellContent(std::vector<std::vector<rtl::OUString> > cellContent) { - if(cellContent.empty()) - { - unsigned int i = m_pImpl->aColumns.size(); - std::vector<rtl::OUString> emptyCells; - while(i!=0) - { - cellContent.push_back(emptyCells); - --i; - } - } - std::vector<rtl::OUString> cCC; - for(::std::vector<std::vector<rtl::OUString> >::iterator iter = cellContent.begin(); iter!= cellContent.end();++iter) - { - cCC = *iter; - m_pImpl->aCellContent.push_back(cCC); - } - } - - std::vector<std::vector<rtl::OUString> > UnoControlTableModel::getCellContent() + //if(cellContent.empty()) + //{ + // unsigned int i = m_pImpl->aColumns.size(); + // std::vector<rtl::OUString>& emptyCells; + // while(i!=0) + // { + // cellContent.push_back(emptyCells); + // --i; + // } + //} + //std::vector<rtl::OUString> cCC; + //for(::std::vector<std::vector<rtl::OUString> >::iterator iter = cellContent.begin(); iter!= cellContent.end();++iter) + //{ + // cCC = *iter; + // m_pImpl->aCellContent.push_back(cCC); + //} + m_pImpl->aCellContent.swap( cellContent ); + } + + std::vector<std::vector<rtl::OUString> >& UnoControlTableModel::getCellContent() { return m_pImpl->aCellContent; } @@ -435,378 +404,8 @@ class UnoControlTableColumn : public IColumnModel } } - std::vector<rtl::OUString> UnoControlTableModel::getRowHeaderName() + std::vector<rtl::OUString>& UnoControlTableModel::getRowHeaderName() { return m_pImpl->aRowHeadersTitle; } -::com::sun::star::uno::Any UnoControlTableModel::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) -{ - ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType, - SAL_STATIC_CAST( ::com::sun::star::awt::grid::XGridControl*, this ), - SAL_STATIC_CAST( ::com::sun::star::awt::grid::XGridDataListener*, this ), - //SAL_STATIC_CAST( com::sun::star::lang::XEventListener*, this ), - //SAL_STATIC_CAST( com::sun::star::awt::XMouseListener*, this ), - SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) ); - return (aRet.hasValue() ? aRet : VCLXWindow::queryInterface( rType )); -} - -// ::com::sun::star::lang::XTypeProvider -IMPL_XTYPEPROVIDER_START( UnoControlTableModel ) - getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridControl>* ) NULL ), - getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel>* ) NULL ), - getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener>* ) NULL ), - VCLXWindow::getTypes() -IMPL_XTYPEPROVIDER_END - -::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel > SAL_CALL UnoControlTableModel::getColumnModel( ) throw (::com::sun::star::uno::RuntimeException) -{ - return NULL; -} -void SAL_CALL UnoControlTableModel::setColumnModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >& model ) throw (::com::sun::star::uno::RuntimeException) -{ - (void)model; -} -::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel > SAL_CALL UnoControlTableModel::getDataModel( ) throw (::com::sun::star::uno::RuntimeException) -{ - return NULL; -} -void SAL_CALL UnoControlTableModel::setDataModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >& model ) throw (::com::sun::star::uno::RuntimeException) -{ - (void)model; -} -sal_Int32 SAL_CALL UnoControlTableModel::getItemIndexAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException) -{ - TableControl* pTableControl = (TableControl*)GetWindow(); - return pTableControl->GetCurrentRow( Point(x,y) ); -} - -/* -void SAL_CALL UnoControlTableModel::addMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener > & listener ) throw(::com::sun::star::uno::RuntimeException) -{ - VCLXWindow::addMouseListener( listener ); -} - -void SAL_CALL UnoControlTableModel::removeMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener > & listener ) throw(::com::sun::star::uno::RuntimeException) -{ - VCLXWindow::removeMouseListener( listener ); -} -*/ -/* -void SAL_CALL UnoControlTableModel::mousePressed( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException) -{ - (void)rEvent; -} -void SAL_CALL UnoControlTableModel::mouseReleased( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException) -{ - (void)rEvent; -} -void SAL_CALL UnoControlTableModel::mouseEntered( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException) -{ - (void) rEvent; -} -void SAL_CALL UnoControlTableModel::mouseExited( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException) -{ - (void) rEvent; -} -*/ -void SAL_CALL UnoControlTableModel::addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException) -{ - (void)listener; -} - -void SAL_CALL UnoControlTableModel::removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException) -{ - (void) listener; -} - -void UnoControlTableModel::setProperty( const ::rtl::OUString& PropertyName, const Any& aValue) throw(RuntimeException) -{ - ::vos::OGuard aGuard( GetMutex() ); - - TableControl* pTableControl = (TableControl*)GetWindow(); - - switch( GetPropertyId( PropertyName ) ) - { - case BASEPROPERTY_GRID_SELECTIONMODE: - { - SelectionType eSelectionType; - if( aValue >>= eSelectionType ) - { - SelectionMode eSelMode; - switch( eSelectionType ) - { - case SelectionType_SINGLE: eSelMode = SINGLE_SELECTION; break; - case SelectionType_RANGE: eSelMode = RANGE_SELECTION; break; - case SelectionType_MULTI: eSelMode = MULTIPLE_SELECTION; break; - // case SelectionType_NONE: - default: eSelMode = NO_SELECTION; break; - } - if( pTableControl->getSelEngine()->GetSelectionMode() != eSelMode ) - pTableControl->getSelEngine()->SetSelectionMode( eSelMode ); - } - break; - } - case BASEPROPERTY_HSCROLL: - { - sal_Bool bHScroll = true; - if( aValue >>= bHScroll ) - { - m_bHScroll = bHScroll; - } - break; - } - case BASEPROPERTY_VSCROLL: - { - sal_Bool bVScroll = true; - if( aValue >>= bVScroll ) - { - m_bVScroll = bVScroll; - } - break; - } - case BASEPROPERTY_GRID_SHOWROWHEADER: - { - sal_Bool rowHeader = true; - if( aValue >>= rowHeader ) - { - setRowHeaders(rowHeader); - } - break; - } - - case BASEPROPERTY_GRID_SHOWCOLUMNHEADER: - { - sal_Bool colHeader = true; - if( aValue >>= colHeader ) - { - setColumnHeaders(colHeader); - } - break; - } - case BASEPROPERTY_GRID_DATAMODEL: - { - m_xDataModel = Reference< XGridDataModel >( aValue, UNO_QUERY ); - Sequence<Sequence< ::rtl::OUString > > cellData = m_xDataModel->getData(); - Sequence<rtl::OUString> rowData(0); - for(int i = 0; i< m_xDataModel->getRowCount();++i) - { - rowData = cellData[i]; - std::vector<rtl::OUString> newRow( - comphelper::sequenceToContainer< std::vector<rtl::OUString > >(rowData)); - if(newRow.size()<m_pImpl->aColumns.size()) - newRow.resize(m_pImpl->aColumns.size(),rtl::OUString::createFromAscii("")); - m_pImpl->aCellContent.push_back(newRow); - } - Sequence< ::rtl::OUString > rowHeaders = m_xDataModel->getRowHeaders(); - std::vector< rtl::OUString > newRow( - comphelper::sequenceToContainer< std::vector<rtl::OUString > >(rowHeaders)); - m_pImpl->nRowCount = m_xDataModel->getRowCount(); - setRowHeaderName(newRow); - break; - } - case BASEPROPERTY_GRID_COLUMNMODEL: - { - m_xColumnModel = Reference< XGridColumnModel >( aValue, UNO_QUERY ); - Sequence<Reference< XGridColumn > > columns = m_xColumnModel->getColumns(); - std::vector<Reference< XGridColumn > > aNewColumns( - comphelper::sequenceToContainer<std::vector<Reference< XGridColumn > > >(columns)); - if(!m_pImpl->aColumns.empty()) - m_pImpl->aColumns.clear(); - for ( ::svt::table::ColPos col = 0; col < m_xColumnModel->getColumnCount(); ++col ) - { - UnoControlTableColumn* tableColumn = new UnoControlTableColumn(aNewColumns[col]); - m_pImpl->aColumns.push_back((PColumnModel)tableColumn); - } - break; - } - default: - VCLXWindow::setProperty( PropertyName, aValue ); - break; - } -} - -Any UnoControlTableModel::getProperty( const ::rtl::OUString& PropertyName ) throw(RuntimeException) -{ - ::vos::OGuard aGuard( GetMutex() ); - - const sal_uInt16 nPropId = GetPropertyId( PropertyName ); - TableControl* pTableControl = (TableControl*)GetWindow(); - if(pTableControl) - { - switch(nPropId) - { - case BASEPROPERTY_GRID_SELECTIONMODE: - { - SelectionType eSelectionType; - - SelectionMode eSelMode = pTableControl->getSelEngine()->GetSelectionMode(); - switch( eSelMode ) - { - case SINGLE_SELECTION: eSelectionType = SelectionType_SINGLE; break; - case RANGE_SELECTION: eSelectionType = SelectionType_RANGE; break; - case MULTIPLE_SELECTION:eSelectionType = SelectionType_MULTI; break; -// case NO_SELECTION: - default: eSelectionType = SelectionType_NONE; break; - } - return Any( eSelectionType ); - } - case BASEPROPERTY_GRID_SHOWROWHEADER: - { - return Any ((sal_Bool) pTableControl->GetModel()->hasRowHeaders()); - } - case BASEPROPERTY_GRID_SHOWCOLUMNHEADER: - return Any ((sal_Bool) pTableControl->GetModel()->hasColumnHeaders()); - case BASEPROPERTY_GRID_DATAMODEL: - return Any ( m_xDataModel ); - case BASEPROPERTY_GRID_COLUMNMODEL: - return Any ( m_xColumnModel); - case BASEPROPERTY_HSCROLL: - return Any ( m_bHScroll); - case BASEPROPERTY_VSCROLL: - return Any ( m_bVScroll); - } - } - return VCLXWindow::getProperty( PropertyName ); -} - -void UnoControlTableModel::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds ) -{ - PushPropertyIds( rIds, - BASEPROPERTY_GRID_SHOWROWHEADER, - BASEPROPERTY_GRID_SHOWCOLUMNHEADER, - BASEPROPERTY_GRID_DATAMODEL, - BASEPROPERTY_GRID_COLUMNMODEL, - BASEPROPERTY_GRID_SELECTIONMODE, - 0); - VCLXWindow::ImplGetPropertyIds( rIds, true ); -} -void SAL_CALL UnoControlTableModel::setVisible( sal_Bool bVisible ) throw(::com::sun::star::uno::RuntimeException) -{ - TableControl* pTable = (TableControl*)GetWindow(); - if ( pTable ) - { - pTable->SetModel(PTableModel(this)); - pTable->Show( bVisible ); - } -} -void SAL_CALL UnoControlTableModel::setFocus() throw(::com::sun::star::uno::RuntimeException) -{ - ::vos::OGuard aGuard( GetMutex() ); - if ( GetWindow()) - GetWindow()->GrabFocus(); -} -void SAL_CALL UnoControlTableModel::rowAdded(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) -{ - std::vector<OUString> aNewRow( - comphelper::sequenceToContainer< std::vector<rtl::OUString > >(Event.rowData)); - if(aNewRow.size()<m_pImpl->aColumns.size()) - aNewRow.resize(m_pImpl->aColumns.size(),rtl::OUString::createFromAscii("")); - m_pImpl->aCellContent.push_back(aNewRow); - if(hasRowHeaders()) - m_pImpl->aRowHeadersTitle.push_back(Event.headerName); - m_pImpl->nRowCount=m_pImpl->aCellContent.size(); - TableControl* pTable = (TableControl*)GetWindow(); - pTable->InvalidateDataWindow(m_pImpl->nRowCount-1, false); - //pTable->GrabFocus(); -} - -void SAL_CALL UnoControlTableModel::rowRemoved(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) -{ - TableControl* pTable = (TableControl*)GetWindow(); - //unsigned int rows =m_pImpl->aCellContent.size()-1; - if(Event.index == -1) - { - if(hasRowHeaders()) - m_pImpl->aRowHeadersTitle.clear(); - m_pImpl->aCellContent.clear(); - } - else - { - pTable->removeSelectedRow(Event.index); - if(m_pImpl->aCellContent.size()>1) - { - if(hasRowHeaders()) - m_pImpl->aRowHeadersTitle.erase(m_pImpl->aRowHeadersTitle.begin()+Event.index); - m_pImpl->aCellContent.erase(m_pImpl->aCellContent.begin()+Event.index); - - } - else - { - if(hasRowHeaders()) - m_pImpl->aRowHeadersTitle.clear(); - m_pImpl->aCellContent.clear(); - //m_pImpl->nRowCount=0; - } - } - //pTable->InvalidateDataWindow(Event.index, true); - setRowCount(m_pImpl->aCellContent.size()); - pTable->InvalidateDataWindow(Event.index, true); - //pTable->Invalidate(); -} - -void SAL_CALL UnoControlTableModel::dataChanged(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) -{ - (void) Event; -} - - void SAL_CALL UnoControlTableModel::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException) - { - VCLXWindow::disposing( Source ); - } - -::sal_Int32 SAL_CALL UnoControlTableModel::getMinSelectionIndex() throw (::com::sun::star::uno::RuntimeException) -{ - return 0; -} - -::sal_Int32 SAL_CALL UnoControlTableModel::getMaxSelectionIndex() throw (::com::sun::star::uno::RuntimeException) -{ - return 0; -} - -void SAL_CALL UnoControlTableModel::insertIndexIntervall(::sal_Int32 start, ::sal_Int32 length) throw (::com::sun::star::uno::RuntimeException) -{ - (void)length; - (void)start; -} - -void SAL_CALL UnoControlTableModel::removeIndexIntervall(::sal_Int32 start, ::sal_Int32 end) throw (::com::sun::star::uno::RuntimeException) -{ - (void)end; - (void)start; -} - -::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL UnoControlTableModel::getSelection() throw (::com::sun::star::uno::RuntimeException) -{ - TableControl* pTable = (TableControl*)GetWindow(); - std::vector<RowPos> selectedRows = pTable->getSelectedRows(); - Sequence<sal_Int32> selectedRowsToSequence(comphelper::containerToSequence(selectedRows)); - return selectedRowsToSequence; -} - -::sal_Bool SAL_CALL UnoControlTableModel::isCellEditable() throw (::com::sun::star::uno::RuntimeException) -{ - return sal_False; -} - -::sal_Bool SAL_CALL UnoControlTableModel::isSelectionEmpty() throw (::com::sun::star::uno::RuntimeException) -{ - return sal_False; -} - -::sal_Bool SAL_CALL UnoControlTableModel::isSelectedIndex(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException) -{ - (void)index; - return sal_False; -} - -void SAL_CALL UnoControlTableModel::selectRow(::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException) -{ - (void)y; -} - -void SAL_CALL UnoControlTableModel::selectColumn(::sal_Int32 x) throw (::com::sun::star::uno::RuntimeException) -{ - (void)x; -} diff --git a/svtools/source/uno/unocontroltablemodel.hxx b/svtools/source/uno/unocontroltablemodel.hxx index 5da9cc871756..fe3d1f28e9ed 100644 --- a/svtools/source/uno/unocontroltablemodel.hxx +++ b/svtools/source/uno/unocontroltablemodel.hxx @@ -43,25 +43,48 @@ #include <toolkit/awt/vclxwindows.hxx> #include <cppuhelper/typeprovider.hxx> #include <cppuhelper/implbase2.hxx> +#include <com/sun/star/awt/grid/XGridColumn.hpp> //#include <toolkit/helper/listenermultiplexer.hxx> using namespace ::svt::table; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt::grid; + +class UnoControlTableColumn : public IColumnModel + { + private: + ColumnID m_nID; + String m_sName; + bool m_bIsResizable; + TableMetrics m_nWidth; + TableMetrics m_nMinWidth; + TableMetrics m_nMaxWidth; + + public: + UnoControlTableColumn(Reference<XGridColumn>); + + // IColumnModel overridables + virtual ColumnID getID() const; + virtual bool setID( const ColumnID _nID ); + virtual String getName() const; + virtual void setName( const String& _rName ); + virtual bool isResizable() const; + virtual void setResizable( bool _bResizable ); + virtual TableMetrics getWidth() const; + virtual void setWidth( TableMetrics _nWidth ); + virtual TableMetrics getMinWidth() const; + virtual void setMinWidth( TableMetrics _nMinWidth ); + virtual TableMetrics getMaxWidth() const; + virtual void setMaxWidth( TableMetrics _nMaxWidth ); + }; struct UnoControlTableModel_Impl; - class UnoControlTableModel : public ITableModel, public ::cppu::ImplInheritanceHelper2< VCLXWindow, ::com::sun::star::awt::grid::XGridControl, - ::com::sun::star::awt::grid::XGridDataListener> + class UnoControlTableModel : public ITableModel { private: UnoControlTableModel_Impl* m_pImpl; - ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >m_xDataModel; - ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >m_xColumnModel; - bool m_bHasColumnHeaders; - bool m_bHasRowHeaders; - bool m_bVScroll; - bool m_bHScroll; - //MouseListenerMultiplexer m_aMouseListeners; public: UnoControlTableModel(); @@ -103,6 +126,7 @@ using namespace ::svt::table; virtual void addTableModelListener( const PTableModelListener& listener ); virtual void removeTableModelListener( const PTableModelListener& listener ); virtual PColumnModel getColumnModel( ColPos column ); + virtual std::vector<PColumnModel>& getColumnModel(); virtual PColumnModel getColumnModelByID( ColumnID id ); virtual PTableRenderer getRenderer() const; virtual PTableInputHandler getInputHandler() const; @@ -112,59 +136,9 @@ using namespace ::svt::table; virtual ScrollbarVisibility getVerticalScrollbarVisibility(int overAllHeight, int actHeight) const; virtual ScrollbarVisibility getHorizontalScrollbarVisibility(int overAllWidth, int actWidth) const; virtual void setCellContent(std::vector<std::vector<rtl::OUString> > cellContent); - virtual std::vector<std::vector<rtl::OUString> > getCellContent(); + virtual std::vector<std::vector<rtl::OUString> >& getCellContent(); virtual void setRowHeaderName(std::vector<rtl::OUString> cellColumnContent); - virtual std::vector<rtl::OUString> getRowHeaderName(); - - //XGridDataListener overridables - virtual void SAL_CALL rowAdded(const ::com::sun::star::awt::grid::GridDataEvent& Event) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL rowRemoved(const ::com::sun::star::awt::grid::GridDataEvent & Event) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL dataChanged(const ::com::sun::star::awt::grid::GridDataEvent & Event) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); - - ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); - void SAL_CALL acquire() throw() { VCLXWindow::acquire(); } - void SAL_CALL release() throw() { VCLXWindow::release(); } - - // ::com::sun::star::lang::XTypeProvider - ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); - ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); - - //::com::sun::star::awt::grid::XGridControl - ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel > SAL_CALL getColumnModel( ) throw (::com::sun::star::uno::RuntimeException); - void SAL_CALL setColumnModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >& model ) throw (::com::sun::star::uno::RuntimeException); - ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel > SAL_CALL getDataModel( ) throw (::com::sun::star::uno::RuntimeException); - void SAL_CALL setDataModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >& model ) throw (::com::sun::star::uno::RuntimeException); - - virtual ::sal_Int32 SAL_CALL getMinSelectionIndex() throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Int32 SAL_CALL getMaxSelectionIndex() throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL insertIndexIntervall(::sal_Int32 start, ::sal_Int32 length) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeIndexIntervall(::sal_Int32 start, ::sal_Int32 end) throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL getSelection() throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Bool SAL_CALL isCellEditable() throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Bool SAL_CALL isSelectionEmpty() throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Bool SAL_CALL isSelectedIndex(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL selectRow(::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL selectColumn(::sal_Int32 x) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException); - virtual ::sal_Int32 SAL_CALL getItemIndexAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException); - - //void SAL_CALL addMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener > & listener ) throw(::com::sun::star::uno::RuntimeException); - //void SAL_CALL removeMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener > & listener ) throw(::com::sun::star::uno::RuntimeException); - //::com::sun::star::awt::XMouseListener - /* - virtual void SAL_CALL mousePressed( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL mouseReleased( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL mouseEntered( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL mouseExited( const ::com::sun::star::awt::MouseEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException); - */ - - void SAL_CALL setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value ) throw(::com::sun::star::uno::RuntimeException); - ::com::sun::star::uno::Any SAL_CALL getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException); - static void ImplGetPropertyIds( std::list< sal_uInt16 > &aIds ); - void SAL_CALL setVisible(sal_Bool bVisible) throw(::com::sun::star::uno::RuntimeException); - void SAL_CALL setFocus() throw(::com::sun::star::uno::RuntimeException); + virtual std::vector<rtl::OUString>& getRowHeaderName(); }; inline void UnoControlTableModel::SetColumnWidth( ColPos _nColumn, TableMetrics _nWidth100thMM ) diff --git a/svtools/source/uno/unoiface.cxx b/svtools/source/uno/unoiface.cxx index 711abe1b6617..a1ff1ad2ac3e 100644 --- a/svtools/source/uno/unoiface.cxx +++ b/svtools/source/uno/unoiface.cxx @@ -54,8 +54,7 @@ #include <svtools/svtreebx.hxx> #include "treecontrolpeer.hxx" -//#include "vclxgridcontrol.hxx" -#include "unocontroltablemodel.hxx" +#include "svtxgridcontrol.hxx" #include <svtools/table/tablecontrol.hxx> namespace @@ -172,10 +171,8 @@ SAL_DLLPUBLIC_EXPORT Window* CreateWindow( VCLXWindow** ppNewComp, const ::com:: { if ( pParent ) { - ::svt::table::TableControl* m_pTable = new ::svt::table::TableControl(pParent, nWinBits); - UnoControlTableModel* pModel = new UnoControlTableModel(); - *ppNewComp = pModel; - pWindow = m_pTable; + pWindow = new ::svt::table::TableControl(pParent, nWinBits); + *ppNewComp = new SVTXGridControl; } else { diff --git a/tools/source/memtools/table.cxx b/tools/source/memtools/table.cxx index ba0dbb8a90f9..75aafddb6c58 100644 --- a/tools/source/memtools/table.cxx +++ b/tools/source/memtools/table.cxx @@ -125,26 +125,37 @@ BOOL Table::Insert( ULONG nKey, void* p ) { USHORT n = 0; USHORT nTempCount = (USHORT)nCount * 2; - void** pNodes = Container::ImpGetOnlyNodes(); - ULONG nCompareKey = (ULONG)(*pNodes); - while ( nKey > nCompareKey ) + //<!--Modified by PengYunQuan for resolving a NULL pointer access + + if( void** pNodes = Container::ImpGetOnlyNodes() ) { - n += 2; - pNodes += 2; - if ( n < nTempCount ) - nCompareKey = (ULONG)(*pNodes); - else + ULONG nCompareKey = (ULONG)(*pNodes); + while ( nKey > nCompareKey ) { - nCompareKey = 0; - break; + n += 2; + pNodes += 2; + if ( n < nTempCount ) + nCompareKey = (ULONG)(*pNodes); + else + { + nCompareKey = 0; + break; + } } - } - // Testen, ob sich der Key schon in der Tabelle befindet - if ( nKey == nCompareKey ) - return FALSE; + // Testen, ob sich der Key schon in der Tabelle befindet + if ( nKey == nCompareKey ) + return FALSE; - i = n; + i = n; + } + else + { + i = 0; + if ( ImplGetIndex( nKey, &i ) != TABLE_ENTRY_NOTFOUND ) + return FALSE; + } + //-->Modified by PengYunQuan for resolving a NULL pointer access } else { diff --git a/transex3/prj/d.lst b/transex3/prj/d.lst index 39bafa4694c6..a469837275ed 100644 --- a/transex3/prj/d.lst +++ b/transex3/prj/d.lst @@ -41,8 +41,10 @@ mkdir: %_DEST%\bin%_EXT%\help\com\sun\star\help ..\%__SRC%\class\receditor\receditor.jar %_DEST%\bin%_EXT%\receditor.jar ..\scripts\localize.pl %_DEST%\bin%_EXT%\localize.pl +..\scripts\localize_old.pl %_DEST%\bin%_EXT%\localize_old.pl ..\scripts\localize %_DEST%\bin%_EXT%\localize ..\scripts\fast_merge.pl %_DEST%\bin%_EXT%\fast_merge.pl +..\scripts\keyidGen.pl %_DEST%\bin%_EXT%\keyidGen.pl ..\inc\export.hxx %_DEST%\inc%_EXT%\transex3\export.hxx ..\inc\transex3\directory.hxx %_DEST%\inc%_EXT%\transex3\directory.hxx diff --git a/transex3/scripts/fast_merge.pl b/transex3/scripts/fast_merge.pl index 266c1c0801e8..7321a9a42911 100644 --- a/transex3/scripts/fast_merge.pl +++ b/transex3/scripts/fast_merge.pl @@ -179,7 +179,7 @@ sub getNextSdfObj } else { - $line =~ /^(([^\t]*)\t([^\t]*).*)/o ; + $line =~ /^(([^\t]*)\t([^\t]*)[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t*)/o ; if( defined $1 && defined $2 && defined $3 ) { $obj->line ( $1 ); diff --git a/transex3/scripts/localize_old.pl b/transex3/scripts/localize_old.pl new file mode 100755 index 000000000000..151399d22002 --- /dev/null +++ b/transex3/scripts/localize_old.pl @@ -0,0 +1,1130 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; + + +#************************************************************************* +# +# 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: localize.pl,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. +# +#************************************************************************* + +use strict; +use Getopt::Long; +use IO::Handle; +use File::Find; +use File::Temp; +use File::Copy; +use File::Glob qw(:glob csh_glob); +use Cwd; + +# ver 1.1 +# +#### module lookup +#use lib ("$ENV{SOLARENV}/bin/modules", "$ENV{COMMON_ENV_TOOLS}/modules"); + +#### module lookup +# OOo conform +my @lib_dirs; +BEGIN { + if ( !defined($ENV{SOLARENV}) ) { + die "No environment found (environment variable SOLARENV is undefined)"; + } + push(@lib_dirs, "$ENV{SOLARENV}/bin/modules"); + push(@lib_dirs, "$ENV{COMMON_ENV_TOOLS}/modules") if defined($ENV{COMMON_ENV_TOOLS}); +} +use lib (@lib_dirs); + +#### globals #### +my $sdffile = ''; +my $no_sort = ''; +my $outputfile = ''; +my $mode = ''; +my $bVerbose="0"; +my $srcpath = ''; +my $WIN; +my $languages; +#my %sl_modules; # Contains all modules where en-US and de is source language +my $use_default_date = '0'; + + # ( leftpart ) ( rightpart ) + # prj file dummy type gid lid helpid pform width lang text helptext qhelptext title timestamp +my $sdf_regex = "((([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*))\t([^\t]*)\t(([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t)([^\t]*))"; +my $file_types = "(src|hrc|xcs|xcu|lng|ulf|xrm|xhp|xcd|xgf|xxl|xrb)"; +# Always use this date to prevent cvs conflicts +my $default_date = "2002-02-02 02:02:02"; + +#### main #### +parse_options(); + +if ( defined $ENV{USE_SHELL} && $ENV{USE_SHELL} eq '4nt' ) { + $WIN = 'TRUE'; +} + else { + $WIN = ''; +} + +#%sl_modules = fetch_sourcelanguage_dirlist(); + + +if ( $mode eq "merge" ) { + merge_gsicheck(); + splitfile( $sdffile ); + unlink $sdffile; # remove temp file! +} +elsif( $mode eq "extract" ) { + collectfiles( $outputfile ); +} +else { + usage(); +} + +exit(0); + +######################################################### +sub splitfile{ + + my $lastFile = ''; + my $currentFile = ''; + my $cur_sdffile = ''; + my $last_sdffile = ''; + my $delim; + my $badDelim; + my $start = 'TRUE'; + my %index = (); + my %block; + + STDOUT->autoflush( 1 ); + + #print STDOUT "Open File $sdffile\n"; + open MYFILE , "< $sdffile" + or die "Can't open '$sdffile'\n"; + + while( <MYFILE>){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + next if( $prj eq "binfilter" ); # Don't merge strings into binfilter module + chomp( $line ); + $currentFile = $srcpath . '\\' . $prj . '\\' . $file; + if ( $WIN ) { $currentFile =~ s/\//\\/g; } + else { $currentFile =~ s/\\/\//g; } + + $cur_sdffile = $currentFile; + #if( $cur_sdffile =~ /\.$file_types[\s]*$/ ){ + if( $WIN ) { $cur_sdffile =~ s/\\[^\\]*\.$file_types[\s]*$/\\localize.sdf/; } + else { $cur_sdffile =~ s/\/[^\/]*\.$file_types[\s]*$/\/localize.sdf/; } + #} + + # Set default date + if( $line =~ /(.*)\t[^\t\$]*$/ ){ + $line = $1."\t".$default_date; + } + + if( $start ){ + $start=''; + $lastFile = $currentFile; # ? + $last_sdffile = $cur_sdffile; + } + + if( $lang eq "en-US" ){} + elsif( $cur_sdffile eq $last_sdffile ) + { + $block{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line ; + } + else + { + writesdf( $lastFile , \%block ); + $lastFile = $currentFile; #? + $last_sdffile = $cur_sdffile; + %block = (); + #if( ! $lang eq "en-US" ) { + $block{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line ; + #} + + } + } #else { print STDOUT "splitfile REGEX kaputt\n";} + + } + writesdf( $lastFile , \%block ); + %block = (); + close( MYFILE ); + +} +######################################################### + +#sub fetch_sourcelanguage_dirlist +#{ +# +# my $working_path = getcwd(); +# my %sl_dirlist; +# +# chdir $srcpath; +# my @all_dirs = csh_glob( "*" ); +# +# foreach my $file ( @all_dirs ) +# { +# if( -d $file ) +# { +# my $module = $file; +# $file .= "/prj/l10n"; +# $file =~ s/\//\\/ , if( $WIN ) ; +# +# if( -f $file ) # Test file <module>/prj/l10n +# { +# $sl_dirlist{ $module } = 1; +# if( $bVerbose eq "1" ) { print STDOUT "$module: de and en-US source language detected\n"; } +# } +# } +# } +# +# chdir $working_path; +# +# return %sl_dirlist; +#} + +#sub has_two_sourcelanguages +#{ +# my $module = shift; +# return defined $sl_modules{ $module } ; +#} +sub writesdf{ + + my $lastFile = shift; + my $blockhash_ref = shift; + my $localizeFile = $lastFile; + my %index=(); + + if( $localizeFile =~ /\.$file_types[\s]*$/ ){ + if( $WIN ) { $localizeFile =~ s/\\[^\\]*\.$file_types[\s]*$/\\localize.sdf/; } + else { $localizeFile =~ s/\/[^\/]*\.$file_types[\s]*$/\/localize.sdf/; } + }else { + print STDERR "Strange filetype found '$localizeFile'\n"; + return; + } + if( open DESTFILE , "< $localizeFile" ){ + + #or die "Can't open/create '\$localizeFile'"; + + #### Build hash + while(<DESTFILE>){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + chomp( $line ); + $index{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line ; + + } #else { print STDOUT "writesdf REGEX kaputt $_\n";} + + } + close( DESTFILE ); + } + #### Copy new strings + my @mykeys = keys( %{ $blockhash_ref } ); + my $isDirty = "FALSE"; + foreach my $key( @mykeys ){ + if( ! defined $index{ $key } ){ + # Add new entry + $index{ $key } = $blockhash_ref->{ $key} ; + $isDirty = "TRUE"; + }elsif( $index{ $key } ne $blockhash_ref->{ $key } ){ + # Overwrite old entry + $index{ $key } = $blockhash_ref->{ $key }; + $isDirty = "TRUE"; + }else { + } + } + + #### Write file + + if( !$bVerbose ){ print STDOUT "."; } + if( $isDirty eq "TRUE" ){ + if( $bVerbose ){ print STDOUT "$localizeFile\n"; } + if( open DESTFILE , "+> $localizeFile" ){ + print DESTFILE get_license_header(); + @mykeys = sort keys( %index ); + foreach my $key( @mykeys ){ + print DESTFILE ( $index{ $key } , "\n" ); + } + close DESTFILE; + }else { + print STDOUT "WARNING: File $localizeFile is not writable , try to merge ...\n"; + my ( $TMPFILE , $tmpfile ) = File::Temp::tempfile(); + if( open DESTFILE , "+> $tmpfile " ){ + @mykeys = keys( %index ); + foreach my $key( @mykeys ){ + print DESTFILE ( $index{ $key } , "\n" ); + } + close DESTFILE; + if( move( $localizeFile , $localizeFile.".backup" ) ){ + if( copy( $tmpfile , $localizeFile ) ){ + unlink $localizeFile.".backup"; + } else { print STDERR "Can't open/create '$localizeFile', original file is renamed to $localizeFile.backup\n"; } + } else { print STDERR "Can't open/create '$localizeFile'\n"; } + }else{ + print STDERR "WARNING: Can't open/create '$localizeFile'\n"; + } + unlink $tmpfile; + } + } +# if( $no_sort eq '' ){ +# sort_outfile( $localizeFile ); +# } +} + +sub get_license_header{ + return +"#\n". +"# #### ### # # ### ##### ##### #### ##### ##### \n". +"# # # # # ## # # # # # # # # # \n". +"# # # # # # # # # # # ### # # # # \n". +"# # # # # # ## # # # # # # # # \n". +"# #### ### # # ### # ##### #### ##### # \n". +"#\n". +"# DO NOT EDIT! This file will be overwritten by localisation process\n". +"#\n". +"#*************************************************************************\n". +"#\n". +"# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n". +"# \n". +"# Copyright 2008 by Sun Microsystems, Inc.\n". +"#\n". +"# OpenOffice.org - a multi-platform office productivity suite\n". +"#\n". +"# \$RCSfile:". +"localize.pl,v \$\n". +"#\n". +"# \$Revision: ". +"1.17.4.1 \$\n". +"#\n". +"# This file is part of OpenOffice.org.\n". +"#\n". +"# OpenOffice.org is free software: you can redistribute it and/or modify\n". +"# it under the terms of the GNU Lesser General Public License version 3\n". +"# only, as published by the Free Software Foundation.\n". +"#\n". +"# OpenOffice.org is distributed in the hope that it will be useful,\n". +"# but WITHOUT ANY WARRANTY; without even the implied warranty of\n". +"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n". +"# GNU Lesser General Public License version 3 for more details\n". +"# (a copy is included in the LICENSE file that accompanied this code).\n". +"#\n". +"# You should have received a copy of the GNU Lesser General Public License\n". +"# version 3 along with OpenOffice.org. If not, see\n". +"# <http://www.openoffice.org/license.html>\n". +"# for a copy of the LGPLv3 License.\n". +"#\n". +"#*************************************************************************\n"; +} +######## Check input sdf file and use only the correct part +sub merge_gsicheck{ + my $command = ''; + my ( $TMPHANDLE , $tmpfile ) = File::Temp::tempfile(); + my ( $TMPHANDLE2 , $tmpfile2 ) = File::Temp::tempfile(); + close ( $TMPHANDLE ); + close ( $TMPHANDLE2 ); + + unlink $tmpfile2; + my $output2 = `cat $sdffile | sort > $tmpfile2`; + my $rc2 = $? << 8; + if( $rc2 ne 0 ){ + printf("ERROR: Failed -> cat $sdffile | sort > $tmpfile2\n$output2\n"); + exit( -1 ); + } + +# if( $ENV{WRAPCMD} ){ +# $command = "$ENV{WRAPCMD} gsicheck"; +# }else{ +# $command = "gsicheck"; +# } +# my $errfile = $tmpfile.".err"; +# $command .= " -k -c -wcf $tmpfile -wef $errfile -l \"\" $tmpfile2"; +# my $output = `$command`; +# my $rc = $? << 8; +# if ( $output ne "" ){ +# print STDOUT "### gsicheck ###\n"; +# print STDOUT "### The file $errfile have been written containing the errors in your sdf file. Those lines will not be merged: ###\n\n"; +# print STDOUT "$output\n"; +# print STDOUT "################\n"; +# +# }else{ +# # Remove the 0 Byte file +# unlink $errfile; +# } + $sdffile = $tmpfile2; +# unlink $tmpfile2; +} +######################################################### +sub collectfiles{ + print STDOUT "### Localize\n"; + my @sdfparticles; + my $localizehash_ref; + my ( $bAll , $bUseLocalize, $langhash_ref , $bHasSourceLanguage , $bFakeEnglish ) = parseLanguages(); + + # Enable autoflush on STDOUT + # $| = 1; + STDOUT->autoflush( 1 ); + + ### Search sdf particles + print STDOUT "### Searching sdf particles\n"; + my $working_path = getcwd(); + chdir $srcpath; + find sub { + my $file = $File::Find::name; + if( -f && $file =~ /.*localize.sdf$/ ) { + push @sdfparticles , $file; + if( $bVerbose eq "1" ) { print STDOUT "$file\n"; } + else { print "."; } + + } + } , getcwd() ;#"."; #$srcpath; + chdir $working_path; + + my $nFound = $#sdfparticles +1; + print "\n $nFound files found !\n"; + + my ( $LOCALIZEPARTICLE , $localizeSDF ) = File::Temp::tempfile(); + close( $LOCALIZEPARTICLE ); + + my ( $ALLPARTICLES_MERGED , $particleSDF_merged ) = File::Temp::tempfile(); + close( $ALLPARTICLES_MERGED ); + my ( $LOCALIZE_LOG , $my_localize_log ) = File::Temp::tempfile(); + close( $LOCALIZE_LOG ); + + ## Get the localize de,en-US extract + if( $bAll || $bUseLocalize ){ + print "### Fetching source language strings\n"; + my $command = ""; + my $args = ""; + + if( $ENV{WRAPCMD} ){ + $command = "$ENV{WRAPCMD} localize_sl"; + }else{ + $command = "localize_sl"; + } + + # -e + # if ( -x $command ){ + if( $command ){ + if( !$bVerbose ){ $args .= " -QQ -skip_links "; } + $args .= " -e -f $localizeSDF -l "; + my $bFlag=""; + if( $bAll ) {$args .= " en-US";} + else{ + my @list; + foreach my $isokey ( keys( %{ $langhash_ref } ) ){ + push @list , $isokey; + if( $langhash_ref->{ $isokey } ne "" ){ + push @list , $langhash_ref->{ $isokey }; + } + } + remove_duplicates( \@list ); + foreach my $isokey ( @list ){ + switch :{ + #( $isokey=~ /^de$/i ) + # && do{ + # if( $bFlag eq "TRUE" ){ $args .= ",de"; } + # else { + # $args .= "de"; $bFlag = "TRUE"; + # } + # }; + ( $isokey=~ /^en-US$/i ) + && do{ + if( $bFlag eq "TRUE" ){ $args .= ",en-US"; } + else { + $args .= "en-US"; $bFlag = "TRUE"; + } + }; + + } #switch + } #foreach + } # if + } # if +# if ( !$bVerbose ){ +# if ( $WIN eq "TRUE" ) { $args .= " > $my_localize_log"; } +# else { $args .= " >& $my_localize_log"; } +# } + if ( $bVerbose ) { print STDOUT $command.$args."\n"; } + + my $rc = system( $command.$args ); + + #my $output = `$command.$args`; + #my $rc = $? << 8; + + if( $rc < 0 ){ print STDERR "ERROR: localize rc = $rc\n"; exit( -1 ); } + ( $localizehash_ref ) = read_file( $localizeSDF , $langhash_ref ); + + } + ## Get sdf particles + open ALLPARTICLES_MERGED , "+>> $particleSDF_merged" + or die "Can't open $particleSDF_merged"; + + ## Fill fackback hash + my( $fallbackhashhash_ref ) = fetch_fallback( \@sdfparticles , $localizeSDF , $langhash_ref ); +# my( $fallbackhashhash_ref ) = fetch_fallback( \@sdfparticles , $localizeSDF , $langhash_ref ); + my %block; + my $cur_fallback; + if( !$bAll) { + foreach my $cur_lang ( keys( %{ $langhash_ref } ) ){ + #print STDOUT "DBG: G1 cur_lang=$cur_lang\n"; + $cur_fallback = $langhash_ref->{ $cur_lang }; + if( $cur_fallback ne "" ){ + # Insert fallback strings + #print STDOUT "DBG: Renaming $cur_fallback to $cur_lang in fallbackhash\n"; + rename_language( $fallbackhashhash_ref , $cur_fallback , $cur_lang ); + } + foreach my $currentfile ( @sdfparticles ){ + if ( open MYFILE , "< $currentfile" ) { + while(<MYFILE>){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + chomp( $line ); + + if ( $lang eq $cur_lang ){ + # Overwrite fallback strings with collected strings + #if( ( !has_two_sourcelanguages( $cur_lang) && $cur_lang eq "de" ) || $cur_lang ne "en-US" ){ + $fallbackhashhash_ref->{ $cur_lang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ; + #} + + } + } + } + }else { print STDERR "WARNING: Can't open file $currentfile"; } + } + + foreach my $line ( keys( %{$fallbackhashhash_ref->{ $cur_lang } } )) { + if( #$cur_lang ne "de" && + $cur_lang ne "en-US" ){ + print ALLPARTICLES_MERGED ( $fallbackhashhash_ref->{ $cur_lang }{ $line }, "\n" ); + } + } + } + } else { + foreach my $currentfile ( @sdfparticles ){ + if ( open MYFILE , "< $currentfile" ) { + while( <MYFILE> ){ + print ALLPARTICLES_MERGED ( $_, "\n" ); # recheck de / en-US ! + } + } + else { print STDERR "WARNING: Can't open file $currentfile"; } + } + } + close ALLPARTICLES_MERGED; + + + # Hash of array + my %output; + my @order; + + ## Join both + if( $outputfile ){ + if( open DESTFILE , "+> $outputfile" ){ + if( !open LOCALIZEPARTICLE , "< $localizeSDF" ) { print STDERR "ERROR: Can't open file $localizeSDF\n"; } + if( !open ALLPARTICLES_MERGED , "< $particleSDF_merged" ) { print STDERR "ERROR: Can't open file $particleSDF_merged\n"; } + + # Insert localize + my $extract_date=""; + while ( <LOCALIZEPARTICLE> ){ + if( /$sdf_regex/ ){ + my $leftpart = defined $2 ? $2 : ''; + my $lang = defined $12 ? $12 : ''; + my $rightpart = defined $13 ? $13 : ''; + my $timestamp = defined $18 ? $18 : ''; + + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + #my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + + if( $use_default_date ) + { + $extract_date = "$default_date\n" ; + } + elsif( $extract_date eq "" ) { + $extract_date = $timestamp ; + $extract_date =~ tr/\r\n//d; + $extract_date .= "\n"; + } + + if( $bAll ){ print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date ; } + else { + foreach my $sLang ( keys( %{ $langhash_ref } ) ){ + if( $sLang=~ /all/i ) { + push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ; + #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date; + } + #if( $sLang eq "de" && $lang eq "de" ) { + # push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ; + #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date; + #} + if( $sLang eq "en-US" && $lang eq "en-US" ) { + push @order , $prj.$gid.$lid.$file.$type.$plattform.$helpid; + if( !$bFakeEnglish ){ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ; } + #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date; + } + + } + } + } + } + # Insert particles + while ( <ALLPARTICLES_MERGED> ){ + if( /$sdf_regex/ ){ + my $leftpart = defined $2 ? $2 : ''; + my $prj = defined $3 ? $3 : ''; + my $lang = defined $12 ? $12 : ''; + my $rightpart = defined $13 ? $13 : ''; + my $timestamp = defined $18 ? $18 : ''; + + #my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + #my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + + if( $use_default_date ) + { + $extract_date = "$default_date\n" ; + } + elsif( $extract_date eq "" ) + { + $extract_date = $timestamp; + } + + if( ! ( $prj =~ /binfilter/i ) ) { + push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ; + #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date ; + } + } + } + + # Write! + foreach my $curkey ( @order ){ + foreach my $curlist ( $output{ $curkey } ){ + foreach my $line ( @{$curlist} ){ + print DESTFILE $line; + } + } + } + + }else { print STDERR "Can't open $outputfile";} + } + close DESTFILE; + close LOCALIZEPARTICLE; + close ALLPARTICLES_MERGED; + + #print STDOUT "DBG: \$localizeSDF $localizeSDF \$particleSDF_merged $particleSDF_merged\n"; + unlink $localizeSDF , $particleSDF_merged , $my_localize_log; + + #sort_outfile( $outputfile ); + #remove_obsolete( $outputfile ) , if $bHasSourceLanguage ne ""; + } + +######################################################### +sub remove_obsolete{ + my $outfile = shift; + my @lines; + my $enusleftpart; + my @good_lines; + + print STDOUT "### Removing obsolete strings\n"; + + # Kick out all strings without en-US reference + if ( open ( SORTEDFILE , "< $outfile" ) ){ + while( <SORTEDFILE> ){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $language = defined $12 ? $12 : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + my $leftpart = $prj.$gid.$lid.$file.$type.$plattform.$helpid; + + if( $language eq "en-US" ){ # source string found, 1. entry + $enusleftpart = $leftpart; + push @good_lines , $line; + }else{ + if( !defined $enusleftpart or !defined $leftpart ){ + print STDERR "BADLINE: $line\n"; + print STDERR "\$enusleftpart = $enusleftpart\n"; + print STDERR "\$leftpart = $leftpart\n"; + } + if( $enusleftpart eq $leftpart ){ # matching language + push @good_lines , $line; + } + #else{ + # print STDERR "OUT: \$enusleftpart=$enusleftpart \$leftpart=$leftpart \$line=$line\n"; + #} + } + } + } + close SORTEDFILE; + } else { print STDERR "ERROR: Can't open file $outfile\n";} + + # Write file + if ( open ( SORTEDFILE , "> $outfile" ) ){ + foreach my $newline ( @good_lines ) { + print SORTEDFILE $newline; + } + close SORTEDFILE; + } else { print STDERR "ERROR: Can't open file $outfile\n";} + +} +######################################################### +sub sort_outfile{ + my $outfile = shift; + print STDOUT "### Sorting ... $outfile ..."; + my @lines; + my @sorted_lines; + + + #if ( open ( SORTEDFILE , "< $outputfile" ) ){ + if ( open ( SORTEDFILE , "< $outfile" ) ){ + my $line; + while ( <SORTEDFILE> ){ + $line = $_; + if( $line =~ /^[^\#]/ ){ + push @lines , $line; + } + } + close SORTEDFILE; + @sorted_lines = sort { + my $xa_lang = ""; + my $xa_left_part = ""; + my $xa_right_part = ""; + my $xa_timestamp = ""; + my $xb_lang = ""; + my $xb_left_part = ""; + my $xb_right_part = ""; + my $xb_timestamp = ""; + my $xa = ""; + my $xb = ""; + my @alist; + my @blist; + + if( $a=~ /$sdf_regex/ ){ + $xa_left_part = defined $2 ? $2 : ''; + $xa_lang = defined $12 ? $12 : ''; + $xa_right_part = defined $13 ? $13 : ''; + $xa_left_part = remove_last_column( $xa_left_part ); + + } + if( $b=~ /$sdf_regex/ ){ + $xb_left_part = defined $2 ? $2 : ''; + $xb_lang = defined $12 ? $12 : ''; + $xb_right_part = defined $13 ? $13 : ''; + $xb_left_part = remove_last_column( $xb_left_part ); + + + } + if( ( $xa_left_part cmp $xb_left_part ) == 0 ){ # Left part equal + if( ( $xa_lang cmp $xb_lang ) == 0 ){ # Lang equal + return ( $xa_right_part cmp $xb_right_part ); # Right part compare + } + elsif( $xa_lang eq "en-US" ) { return -1; } # en-US wins + elsif( $xb_lang eq "en-US" ) { return 1; } # en-US wins + else { return $xa_lang cmp $xb_lang; } # lang compare + } + else { + return $xa_left_part cmp $xb_left_part; # Left part compare + } + } @lines; + + if ( open ( SORTEDFILE , "> $outfile" ) ){ + print SORTEDFILE get_license_header(); + foreach my $newline ( @sorted_lines ) { + print SORTEDFILE $newline; + #print STDOUT $newline; + } + } + close SORTEDFILE; + } else { print STDERR "WARNING: Can't open file $outfile\n";} + print "done\n"; + +} +######################################################### +sub remove_last_column{ + my $string = shift; + my @alist = split ( "\t" , $string ); + pop @alist; + return join( "\t" , @alist ); +} + +######################################################### +sub rename_language{ + my $fallbackhashhash_ref = shift; + my $cur_fallback = shift; + my $cur_lang = shift; + my $line; + + foreach my $key( keys ( %{ $fallbackhashhash_ref->{ $cur_fallback } } ) ){ + $line = $fallbackhashhash_ref->{ $cur_fallback }{ $key }; + if( $line =~ /$sdf_regex/ ){ + my $leftpart = defined $2 ? $2 : ''; + my $lang = defined $12 ? $12 : ''; + my $rightpart = defined $13 ? $13 : ''; + + $fallbackhashhash_ref->{ $cur_lang }{ $key } = $leftpart."\t".$cur_lang."\t".$rightpart; + } + } +} + +############################################################ +sub remove_duplicates{ + my $list_ref = shift; + my %tmphash; + foreach my $key ( @{ $list_ref } ){ $tmphash{ $key } = '' ; } + @{$list_ref} = keys( %tmphash ); +} + +############################################################## +sub fetch_fallback{ + my $sdfparticleslist_ref = shift; + my $localizeSDF = shift; + my $langhash_ref = shift; + my %fallbackhashhash; + my $cur_lang; + my @langlist; + + foreach my $key ( keys ( %{ $langhash_ref } ) ){ + $cur_lang = $langhash_ref->{ $key }; + if ( $cur_lang ne "" ) { + push @langlist , $cur_lang; + } + } + remove_duplicates( \@langlist ); + foreach $cur_lang ( @langlist ){ + if( $cur_lang eq "en-US" ){ + read_fallbacks_from_source( $localizeSDF , $cur_lang , \%fallbackhashhash ); + } + } + + # remove de / en-US + my @tmplist; + foreach $cur_lang( @langlist ){ + if( $cur_lang ne "en-US" ){ + push @tmplist , $cur_lang; + + } + } + @langlist = @tmplist; + if ( $#langlist +1 ){ + read_fallbacks_from_particles( $sdfparticleslist_ref , \@langlist , \%fallbackhashhash ); + + } + return (\%fallbackhashhash); +} + +######################################################### +sub write_file{ + + my $localizeFile = shift; + my $index_ref = shift; + + if( open DESTFILE , "+> $localizeFile" ){ + foreach my $key( %{ $index_ref } ){ + print DESTFILE ($index_ref->{ $key }, "\n" ); + } + close DESTFILE; + }else { + print STDERR "Can't open/create '$localizeFile'"; + } +} + +######################################################### +sub read_file{ + + my $sdffile = shift; + my $langhash_ref = shift; + my %block = (); + + open MYFILE , "< $sdffile" + or die "Can't open '$sdffile'\n"; + while( <MYFILE>){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $plattform = defined $10 ? $10 : ''; + my $lang = defined $12 ? $12 : ''; + my $helpid = defined $9 ? $9 : ''; + + foreach my $isolang ( keys ( %{ $langhash_ref } ) ){ + if( $isolang=~ /$lang/i || $isolang=~ /all/i ) { $block{$prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ; } + } + } + } + return (\%block); +} + +######################################################### +sub read_fallbacks_from_particles{ + + my $sdfparticleslist_ref = shift; + my $isolanglist_ref = shift; + my $fallbackhashhash_ref = shift; + my $block_ref; + foreach my $currentfile ( @{ $sdfparticleslist_ref } ){ + if ( open MYFILE , "< $currentfile" ) { + while(<MYFILE>){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + my $helpid = defined $9 ? $9 : ''; + + chomp( $line ); + + foreach my $isolang ( @{$isolanglist_ref} ){ + if( $isolang=~ /$lang/i ) { + $fallbackhashhash_ref->{ $isolang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ; + } + } + } + } + }else { print STDERR "WARNING: Can't open file $currentfile"; } + } +} + +######################################################### +sub read_fallbacks_from_source{ + + my $sdffile = shift; + my $isolang = shift; + my $fallbackhashhash_ref = shift; + my $block_ref; + # read fallback for single file + open MYFILE , "< $sdffile" + or die "Can't open '$sdffile'\n"; + + while( <MYFILE>){ + if( /$sdf_regex/ ){ + my $line = defined $_ ? $_ : ''; + my $prj = defined $3 ? $3 : ''; + my $file = defined $4 ? $4 : ''; + my $type = defined $6 ? $6 : ''; + my $gid = defined $7 ? $7 : ''; + my $lid = defined $8 ? $8 : ''; + my $helpid = defined $9 ? $9 : ''; + my $lang = defined $12 ? $12 : ''; + my $plattform = defined $10 ? $10 : ''; + + chomp( $line ); + if( $isolang=~ /$lang/i ) { $fallbackhashhash_ref->{ $isolang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ; + } + } + } +} + +######################################################### +sub parseLanguages{ + + my $bAll; + my $bUseLocalize; + my $bHasSourceLanguage=""; + my $bFakeEnglish=""; + my %langhash; + my $iso=""; + my $fallback=""; + + #### -l all + if( $languages=~ /all/ ){ + $bAll = "TRUE"; + $bHasSourceLanguage = "TRUE"; + } + ### -l fr=de,de + elsif( $languages=~ /.*,.*/ ){ + my @tmpstr = split "," , $languages; + for my $lang ( @tmpstr ){ + if( $lang=~ /([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)(=([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*))?/ ){ + $iso = $1; + $fallback = $4; + + if( ( $iso && $iso=~ /(en-US)/i ) || ( $fallback && $fallback=~ /(en-US)/i ) ) { + $bUseLocalize = "TRUE"; + } + if( ( $iso && $iso=~ /(en-US)/i ) ) { + $bHasSourceLanguage = "TRUE"; + } + if( $fallback ) { $langhash{ $iso } = $fallback; } + else { $langhash{ $iso } = ""; } + } + } + } + ### -l de + else{ + if( $languages=~ /([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)(=([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*))?/ ){ + $iso = $1; + $fallback = $4; + + if( ( $iso && $iso=~ /(en-US)/i ) || ( $fallback && $fallback=~ /(en-US)/i ) ) { + $bUseLocalize = "TRUE"; + + } + if( ( $iso && $iso=~ /(en-US)/i ) ) { + $bHasSourceLanguage = "TRUE"; + } + + if( $fallback ) { $langhash{ $iso } = $fallback; } + else { $langhash{ $iso } = ""; } + } + } + # HACK en-US always needed! + if( !$bHasSourceLanguage ){ + #$bHasSourceLanguage = "TRUE"; + $bUseLocalize = "TRUE"; + $bFakeEnglish = "TRUE"; + $langhash{ "en-US" } = ""; + } + return ( $bAll , $bUseLocalize , \%langhash , $bHasSourceLanguage, $bFakeEnglish); +} + +######################################################### +sub parse_options{ + + my $help; + my $merge; + my $extract; + my $success = GetOptions('f=s' => \$sdffile , 'l=s' => \$languages , 's=s' => \$srcpath , 'h' => \$help , 'v' => \$bVerbose , + 'm' => \$merge , 'e' => \$extract , 'x' => \$no_sort , 'd' => \$use_default_date ); + $outputfile = $sdffile; + + #print STDOUT "DBG: lang = $languages\n"; + if( !$srcpath ){ + #$srcpath = "$ENV{SRC_ROOT}"; + if( !$srcpath ){ + print STDERR "No path to the source root found!\n\n"; + usage(); + exit(1); + } + } + if( $help || !$success || $#ARGV > 1 || ( !$sdffile ) ){ + usage(); + exit(1); + } + if( $merge && $sdffile && ! ( -r $sdffile)){ + print STDERR "Can't open file '$sdffile'\n"; + exit(1); + } + if( !( $languages=~ /[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*(=[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)?(,[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*(=[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)?)*/ ) ){ + print STDERR "Please check the -l iso code\n"; + exit(1); + } + if( ( !$merge && !$extract ) || ( $merge && $extract ) ){ usage();exit( -1 );} + if( $extract ){ $mode = "extract"; } + else { $mode = "merge"; } +} + +######################################################### +sub usage{ + + print STDERR "Usage: localize.pl\n"; + print STDERR "Split or collect SDF files\n"; + print STDERR " merge: -m -f <sdffile> -l l1[=f1][,l2[=f2]][...] [ -s <sourceroot> ]\n"; + print STDERR " extract: -e -f <outputfile> -l <lang> [ -s <sourceroot> ] [-d]\n"; + print STDERR "Options:\n"; + print STDERR " -h help\n"; + print STDERR " -m Merge mode\n"; + print STDERR " -e Extract mode\n"; + print STDERR " -f <sdffile> To split a big SDF file into particles\n"; + print STDERR " <outputfile> To collect and join all particles to one big file\n"; + print STDERR " -s <sourceroot> Path to the modules, if no \$SRC_ROOT is set\n"; + print STDERR " -l ( all | <isocode> | <isocode>=fallback ) comma seperated languages\n"; + print STDERR " -d Use default date in extracted sdf file\n"; + print STDERR " -v Verbose\n"; + print STDERR "\nExample:\n"; + print STDERR "\nlocalize -e -l en-US,pt-BR=en-US -f my.sdf\n( Extract en-US and pt-BR with en-US fallback )\n"; + print STDERR "\nlocalize -m -l cs -f my.sdf\n( Merge cs translation into the sourcecode ) \n"; +} + +# my $line = defined $_ ? $_ : ''; +# my $leftpart = defined $2 ? $2 : ''; +# my $prj = defined $3 ? $3 : ''; +# my $file = defined $4 ? $4 : ''; +# my $dummy = defined $5 ? $5 : ''; +# my $type = defined $6 ? $6 : ''; +# my $gid = defined $7 ? $7 : ''; +# my $lid = defined $8 ? $8 : ''; +# my $helpid = defined $9 ? $9 : ''; +# my $plattform = defined $10 ? $10 : ''; +# my $width = defined $11 ? $11 : ''; +# my $lang = defined $12 ? $12 : ''; +# my $rightpart = defined $13 ? $13 : ''; +# my $text = defined $14 ? $14 : ''; +# my $helptext = defined $15 ? $15 : ''; +# my $quickhelptext = defined $16 ? $16 : ''; +# my $title = defined $17 ? $17 : ''; +# my $timestamp = defined $18 ? $18 : ''; + diff --git a/vcl/aqua/source/gdi/salatslayout.cxx b/vcl/aqua/source/gdi/salatslayout.cxx index 3021e85fed5c..1387a46c6345 100755 --- a/vcl/aqua/source/gdi/salatslayout.cxx +++ b/vcl/aqua/source/gdi/salatslayout.cxx @@ -70,12 +70,13 @@ private: // to prevent ATS overflowing the Fixed16.16 values // ATS font requests get size limited by downscaling huge fonts // in these cases the font scale becomes something bigger than 1.0 - float mfFontScale; + float mfFontScale; private: bool InitGIA( ImplLayoutArgs* pArgs = NULL ) const; bool GetIdealX() const; bool GetDeltaY() const; + void InvalidateMeasurements(); int Fixed2Vcl( Fixed ) const; // convert ATSU-Fixed units to VCL units int AtsuPix2Vcl( int ) const; // convert ATSU-Pixel units to VCL units @@ -310,7 +311,7 @@ void ATSLayout::AdjustLayout( ImplLayoutArgs& rArgs ) mnTrailingSpaceWidth = rArgs.mpDXArray[ mnCharCount-1 ]; if( i > 0 ) mnTrailingSpaceWidth -= rArgs.mpDXArray[ i-1 ]; - InitGIA(); // ensure valid mpCharWidths[] + InitGIA(); // ensure valid mpCharWidths[], TODO: use GetIdealX() instead? mnTrailingSpaceWidth -= Fixed2Vcl( mpCharWidths[i] ); // ignore trailing space for calculating the available width nOrigWidth -= mnTrailingSpaceWidth; @@ -324,11 +325,15 @@ void ATSLayout::AdjustLayout( ImplLayoutArgs& rArgs ) if( !nPixelWidth ) return; - // HACK: justification requests which change the width by just one pixel are probably + // HACK: justification requests which change the width by just one pixel were probably // #i86038# introduced by lossy conversions between integer based coordinate system + // => ignoring such requests has many more benefits than eventual drawbacks if( (nOrigWidth >= nPixelWidth-1) && (nOrigWidth <= nPixelWidth+1) ) return; + // changing the layout will make all previous measurements invalid + InvalidateMeasurements(); + ATSUAttributeTag nTags[3]; ATSUAttributeValuePtr nVals[3]; ByteCount nBytes[3]; @@ -352,7 +357,7 @@ void ATSLayout::AdjustLayout( ImplLayoutArgs& rArgs ) if( eStatus != noErr ) return; - // check result of the justied layout + // update the measurements of the justified layout to match the justification request if( rArgs.mpDXArray ) InitGIA( &rArgs ); } @@ -1069,6 +1074,23 @@ bool ATSLayout::GetDeltaY() const return true; } +// ----------------------------------------------------------------------- + +#define DELETEAZ( X ) { delete[] X; X = NULL; } + +void ATSLayout::InvalidateMeasurements() +{ + mnGlyphCount = -1; + DELETEAZ( mpGlyphIds ); + DELETEAZ( mpCharWidths ); + DELETEAZ( mpChars2Glyphs ); + DELETEAZ( mpGlyphs2Chars ); + DELETEAZ( mpGlyphRTLFlags ); + DELETEAZ( mpGlyphAdvances ); + DELETEAZ( mpGlyphOrigAdvs ); + DELETEAZ( mpDeltaY ); +} + // ======================================================================= #if 0 diff --git a/vcl/aqua/source/gdi/salgdi.cxx b/vcl/aqua/source/gdi/salgdi.cxx index f389abd19a82..1c9bdda3fbdb 100644 --- a/vcl/aqua/source/gdi/salgdi.cxx +++ b/vcl/aqua/source/gdi/salgdi.cxx @@ -404,6 +404,16 @@ void AquaSalGraphics::initResolution( NSWindow* pWin ) DBG_ERROR( "no screen found" ); } + // #i107076# maintaining size-WYSIWYG-ness causes many problems for + // low-DPI, high-DPI or for mis-reporting devices + // => it is better to limit the calculation result then + static const int nMinDPI = 72; + if( (mnRealDPIX < nMinDPI) || (mnRealDPIY < nMinDPI) ) + mnRealDPIX = mnRealDPIY = nMinDPI; + static const int nMaxDPI = 200; + if( (mnRealDPIX > nMaxDPI) || (mnRealDPIY > nMaxDPI) ) + mnRealDPIX = mnRealDPIY = nMaxDPI; + // for OSX any anisotropy reported for the display resolution is best ignored (e.g. TripleHead2Go) mnRealDPIX = mnRealDPIY = (mnRealDPIX + mnRealDPIY + 1) / 2; @@ -931,27 +941,29 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol AddPolygonToPath( xPath, rPolygon, true, !getAntiAliasB2DDraw(), IsPenVisible() ); } - // use the path to prepare the graphics context - CGContextSaveGState( mrContext ); - CGContextBeginPath( mrContext ); - CGContextAddPath( mrContext, xPath ); const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); - CGPathRelease( xPath ); - #ifndef NO_I97317_WORKAROUND // #i97317# workaround for Quartz having problems with drawing small polygons - if( (aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125) ) - return true; + if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) #endif + { + // use the path to prepare the graphics context + CGContextSaveGState( mrContext ); + CGContextBeginPath( mrContext ); + CGContextAddPath( mrContext, xPath ); + + // draw path with antialiased polygon + CGContextSetShouldAntialias( mrContext, true ); + CGContextSetAlpha( mrContext, 1.0 - fTransparency ); + CGContextDrawPath( mrContext, kCGPathEOFillStroke ); + CGContextRestoreGState( mrContext ); + + // mark modified rectangle as updated + RefreshRect( aRefreshRect ); + } - // draw path with antialiased polygon - CGContextSetShouldAntialias( mrContext, true ); - CGContextSetAlpha( mrContext, 1.0 - fTransparency ); - CGContextDrawPath( mrContext, kCGPathEOFillStroke ); - CGContextRestoreGState( mrContext ); + CGPathRelease( xPath ); - // mark modified rectangle as updated - RefreshRect( aRefreshRect ); return true; } @@ -991,27 +1003,28 @@ bool AquaSalGraphics::drawPolyLine( const ::basegfx::B2DPolygon& rPolyLine, CGMutablePathRef xPath = CGPathCreateMutable(); AddPolygonToPath( xPath, rPolyLine, rPolyLine.isClosed(), !getAntiAliasB2DDraw(), true ); - // use the path to prepare the graphics context - CGContextSaveGState( mrContext ); - CGContextAddPath( mrContext, xPath ); const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); - CGPathRelease( xPath ); - #ifndef NO_I97317_WORKAROUND // #i97317# workaround for Quartz having problems with drawing small polygons - if( (aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125) ) - return true; + if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) #endif + { + // use the path to prepare the graphics context + CGContextSaveGState( mrContext ); + CGContextAddPath( mrContext, xPath ); + // draw path with antialiased line + CGContextSetShouldAntialias( mrContext, true ); + CGContextSetLineJoin( mrContext, aCGLineJoin ); + CGContextSetLineWidth( mrContext, rLineWidths.getX() ); + CGContextDrawPath( mrContext, kCGPathStroke ); + CGContextRestoreGState( mrContext ); + + // mark modified rectangle as updated + RefreshRect( aRefreshRect ); + } - // draw path with antialiased line - CGContextSetShouldAntialias( mrContext, true ); - CGContextSetLineJoin( mrContext, aCGLineJoin ); - CGContextSetLineWidth( mrContext, rLineWidths.getX() ); - CGContextDrawPath( mrContext, kCGPathStroke ); - CGContextRestoreGState( mrContext ); + CGPathRelease( xPath ); - // mark modified rectangle as updated - RefreshRect( aRefreshRect ); return true; } diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm index 0305b4cadb43..aabc287dc885 100755 --- a/vcl/aqua/source/window/salframeview.mm +++ b/vcl/aqua/source/window/salframeview.mm @@ -1332,11 +1332,32 @@ private: { mbNeedSpecialKeyHandle = true; } + + // FIXME: + // #i106901# + // if we come here outside of mbInKeyInput, this is likely to be because + // of the keyboard viewer. For unknown reasons having no marked range + // in this case causes a crash. So we say we have a marked range anyway + // This is a hack, since it is not understood what a) causes that crash + // and b) why we should have a marked range at this point. + if( ! mbInKeyInput ) + bHasMarkedText = YES; + return bHasMarkedText; } - (NSRange)markedRange { + // FIXME: + // #i106901# + // if we come here outside of mbInKeyInput, this is likely to be because + // of the keyboard viewer. For unknown reasons having no marked range + // in this case causes a crash. So we say we have a marked range anyway + // This is a hack, since it is not understood what a) causes that crash + // and b) why we should have a marked range at this point. + if( ! mbInKeyInput ) + return NSMakeRange( 0, 0 ); + return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 ); } diff --git a/vcl/inc/vcl/svapp.hxx b/vcl/inc/vcl/svapp.hxx index 1e0c5218d1c5..3e9a1cc55019 100644 --- a/vcl/inc/vcl/svapp.hxx +++ b/vcl/inc/vcl/svapp.hxx @@ -287,6 +287,9 @@ public: static vos::OThread::TThreadIdentifier GetMainThreadIdentifier(); static ULONG ReleaseSolarMutex(); static void AcquireSolarMutex( ULONG nCount ); + static void EnableNoYieldMode( bool i_bNoYield ); + static void AddPostYieldListener( const Link& i_rListener ); + static void RemovePostYieldListener( const Link& i_rListener ); static BOOL IsInMain(); static BOOL IsInExecute(); diff --git a/vcl/inc/vcl/svdata.hxx b/vcl/inc/vcl/svdata.hxx index 12c595350472..d912c172baa5 100644 --- a/vcl/inc/vcl/svdata.hxx +++ b/vcl/inc/vcl/svdata.hxx @@ -111,6 +111,7 @@ class ImplWheelWindow; class SalTimer; class SalI18NImeStatus; class DockingManager; +class VclEventListeners2; namespace vos { class OMutex; } namespace vos { class OCondition; } @@ -137,7 +138,6 @@ struct ImplSVAppData ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; String* mpMSFTempFileName; - AllSettings* mpSettings; // Application settings LocaleConfigurationListener* mpCfgListener; VclEventListeners* mpEventListeners; // listeners for vcl events (eg, extended toolkit) VclEventListeners* mpKeyListeners; // listeners for key events only (eg, extended toolkit) @@ -153,19 +153,22 @@ struct ImplSVAppData ImplWheelWindow* mpWheelWindow; // WheelWindow ImplHotKey* mpFirstHotKey; // HotKey-Verwaltung ImplEventHook* mpFirstEventHook; // Event-Hooks - ULONG mnLastInputTime; // GetLastInputTime() - USHORT mnDispatchLevel; // DispatchLevel - USHORT mnModalMode; // ModalMode Count - USHORT mnModalDialog; // ModalDialog Count - USHORT mnAccessCount; // AccessHdl Count - USHORT mnSysWinMode; // Modus, wann SystemWindows erzeugt werden sollen - USHORT mnLayout; // --- RTL-Flags --- currently not used, only for testing - short mnDialogScaleX; // Scale X-Positions and sizes in Dialogs - BOOL mbInAppMain; // is Application::Main() on stack - BOOL mbInAppExecute; // is Application::Execute() on stack - BOOL mbAppQuit; // is Application::Quit() called - BOOL mbSettingsInit; // TRUE: Settings are init - BOOL mbDialogCancel; // TRUE: Alle Dialog::Execute()-Aufrufe werden mit return FALSE sofort beendet + VclEventListeners2* mpPostYieldListeners; // post yield listeners + ULONG mnLastInputTime; // GetLastInputTime() + USHORT mnDispatchLevel; // DispatchLevel + USHORT mnModalMode; // ModalMode Count + USHORT mnModalDialog; // ModalDialog Count + USHORT mnAccessCount; // AccessHdl Count + USHORT mnSysWinMode; // Modus, wann SystemWindows erzeugt werden sollen + USHORT mnLayout; // --- RTL-Flags --- currently not used, only for testing + short mnDialogScaleX; // Scale X-Positions and sizes in Dialogs + BOOL mbInAppMain; // is Application::Main() on stack + BOOL mbInAppExecute; // is Application::Execute() on stack + BOOL mbAppQuit; // is Application::Quit() called + BOOL mbSettingsInit; // TRUE: Settings are initialized + BOOL mbDialogCancel; // TRUE: Alle Dialog::Execute()-Aufrufe werden mit return FALSE sofort beendet + BOOL mbNoYield; // Application::Yield will not wait for events if the queue is empty + // essentially that makes it the same as Application::Reschedule /** Controls whether showing any IME status window is toggled on or off. diff --git a/vcl/inc/vcl/vclevent.hxx b/vcl/inc/vcl/vclevent.hxx index ff0639d70e82..74971f62c5a6 100644 --- a/vcl/inc/vcl/vclevent.hxx +++ b/vcl/inc/vcl/vclevent.hxx @@ -31,11 +31,13 @@ #ifndef _VCL_VCLEVENT_HXX #define _VCL_VCLEVENT_HXX -#include <tools/link.hxx> -#include <tools/rtti.hxx> -#include <vcl/dllapi.h> +#include "tools/link.hxx" +#include "tools/rtti.hxx" +#include "vcl/dllapi.h" +#include "vcl/impdel.hxx" #include <list> +#include <vector> class Window; class Menu; @@ -251,4 +253,29 @@ public: BOOL Process( VclSimpleEvent* pEvent ) const; }; +class VCL_DLLPUBLIC VclEventListeners2 : public vcl::DeletionNotifier +{ + std::list< Link > m_aListeners; + + struct ListenerIt + { + std::list< Link >::iterator m_aIt; + bool m_bWasInvalidated; + + ListenerIt() : m_bWasInvalidated( false ) {} + }; + + std::vector< ListenerIt > m_aIterators; + + +public: + VclEventListeners2(); + ~VclEventListeners2(); + + void addListener( const Link& ); + void removeListener( const Link& ); + + void callListeners( VclSimpleEvent* ); +}; + #endif // _VCL_VCLEVENT_HXX diff --git a/vcl/prj/d.lst b/vcl/prj/d.lst index 983628184177..54af0d2e289d 100644 --- a/vcl/prj/d.lst +++ b/vcl/prj/d.lst @@ -58,6 +58,7 @@ mkdir: %_DEST%\inc%_EXT%\vcl ..\inc\vcl\imagerepository.hxx %_DEST%\inc%_EXT%\vcl\imagerepository.hxx ..\inc\vcl\imgcons.hxx %_DEST%\inc%_EXT%\vcl\imgcons.hxx ..\inc\vcl\imgctrl.hxx %_DEST%\inc%_EXT%\vcl\imgctrl.hxx +..\inc\vcl\impdel.hxx %_DEST%\inc%_EXT%\vcl\impdel.hxx ..\inc\vcl\inputctx.hxx %_DEST%\inc%_EXT%\vcl\inputctx.hxx ..\inc\vcl\javachild.hxx %_DEST%\inc%_EXT%\vcl\javachild.hxx ..\inc\vcl\jobset.hxx %_DEST%\inc%_EXT%\vcl\jobset.hxx diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index ffb4e94fc775..7f329f2d24d5 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -31,59 +31,49 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" -#ifndef _SV_SVSYS_HXX -#include <svsys.h> -#endif -#include <vcl/salinst.hxx> -#include <vcl/salframe.hxx> -#include <vcl/salsys.hxx> -#ifndef _VOS_PROCESS_HXX -#include <vos/process.hxx> -#endif -#ifndef _VOS_MUTEX_HXX -#include <vos/mutex.hxx> -#endif -#include <tools/tools.h> -#include <tools/debug.hxx> -#include <tools/time.hxx> -#include <vcl/svdata.hxx> -#include <vcl/settings.hxx> -#ifndef _ACCMGR_HXX -#include <vcl/accmgr.hxx> -#endif -#ifndef _SV_KEYCOD_HXX -#include <vcl/keycod.hxx> -#endif -#include <vcl/event.hxx> -#include <vcl/virdev.hxx> -#include <vcl/windata.hxx> -#include <vcl/window.h> -#include <vcl/wrkwin.hxx> -#include <vcl/idlemgr.hxx> -#include <vcl/svapp.hxx> -#include <vcl/cvtgrf.hxx> -#include <vcl/unowrap.hxx> -#include <vcl/xconnection.hxx> -#ifndef _SV_SVIDS_HRC -#include <vcl/svids.hrc> -#endif -#include <vcl/timer.hxx> - -#include <vcl/unohelp.hxx> - -#include <com/sun/star/uno/Reference.h> -#include <com/sun/star/awt/XToolkit.hpp> -#include <com/sun/star/uno/XNamingService.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <comphelper/processfactory.hxx> - -#include <osl/module.h> -#include <osl/file.hxx> +#include "svsys.h" +#include "vcl/salinst.hxx" +#include "vcl/salframe.hxx" +#include "vcl/salsys.hxx" +#include "vos/process.hxx" +#include "vos/mutex.hxx" +#include "tools/tools.h" +#include "tools/debug.hxx" +#include "tools/time.hxx" +#include "i18npool/mslangid.hxx" +#include "vcl/svdata.hxx" +#include "vcl/settings.hxx" +#include "vcl/accmgr.hxx" +#include "vcl/keycod.hxx" +#include "vcl/event.hxx" +#include "vcl/vclevent.hxx" +#include "vcl/virdev.hxx" +#include "vcl/windata.hxx" +#include "vcl/window.h" +#include "vcl/wrkwin.hxx" +#include "vcl/idlemgr.hxx" +#include "vcl/svapp.hxx" +#include "vcl/cvtgrf.hxx" +#include "vcl/unowrap.hxx" +#include "vcl/xconnection.hxx" +#include "vcl/svids.hrc" +#include "vcl/timer.hxx" + +#include "vcl/unohelp.hxx" + +#include "com/sun/star/uno/Reference.h" +#include "com/sun/star/awt/XToolkit.hpp" +#include "com/sun/star/uno/XNamingService.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "comphelper/processfactory.hxx" + +#include "osl/module.h" +#include "osl/file.hxx" #include "osl/thread.h" #include "rtl/tencinfo.h" -#include <rtl/instance.hxx> -#include <vcl/salimestatus.hxx> +#include "rtl/instance.hxx" +#include "vcl/salimestatus.hxx" #include <utility> #include <vcl/lazydelete.hxx> @@ -467,7 +457,7 @@ void Application::Execute() // ----------------------------------------------------------------------- -void Application::Reschedule( bool bAllEvents ) +inline void ImplYield( bool i_bWait, bool i_bAllEvents ) { ImplSVData* pSVData = ImplGetSVData(); @@ -477,34 +467,45 @@ void Application::Reschedule( bool bAllEvents ) Timer::ImplTimerCallbackProc(); pSVData->maAppData.mnDispatchLevel++; - pSVData->mpDefInst->Yield( false, bAllEvents ); + // do not wait for events if application was already quit; in that + // case only dispatch events already available + // do not wait for events either if the app decided that it is too busy for timers + // (feature added for the slideshow) + pSVData->mpDefInst->Yield( i_bWait && !pSVData->maAppData.mbAppQuit && !pSVData->maAppData.mbNoYield, i_bAllEvents ); pSVData->maAppData.mnDispatchLevel--; // flush lazy deleted objects if( pSVData->maAppData.mnDispatchLevel == 0 ) vcl::LazyDelete::flush(); + + // the system timer events will not necesseraly come in in non waiting mode + // e.g. on aqua; need to trigger timer checks manually + if( pSVData->maAppData.mbNoYield && !pSVData->mbNoCallTimer ) + { + do + { + Timer::ImplTimerCallbackProc(); + } + while( pSVData->mbNotAllTimerCalled ); + } + + // call post yield listeners + if( pSVData->maAppData.mpPostYieldListeners ) + pSVData->maAppData.mpPostYieldListeners->callListeners( NULL ); } // ----------------------------------------------------------------------- -void Application::Yield( bool bAllEvents ) +void Application::Reschedule( bool i_bAllEvents ) { - ImplSVData* pSVData = ImplGetSVData(); - - // run timers that have timed out - if ( !pSVData->mbNoCallTimer ) - while ( pSVData->mbNotAllTimerCalled ) - Timer::ImplTimerCallbackProc(); + ImplYield( false, i_bAllEvents ); +} - // do not wait for events if application was already quit; in that - // case only dispatch events already available - pSVData->maAppData.mnDispatchLevel++; - pSVData->mpDefInst->Yield( !pSVData->maAppData.mbAppQuit, bAllEvents ); - pSVData->maAppData.mnDispatchLevel--; +// ----------------------------------------------------------------------- - // flush lazy deleted objects - if( pSVData->maAppData.mnDispatchLevel == 0 ) - vcl::LazyDelete::flush(); +void Application::Yield( bool i_bAllEvents ) +{ + ImplYield( true, i_bAllEvents ); } // ----------------------------------------------------------------------- @@ -1196,6 +1197,33 @@ void Application::RemoveIdleHdl( const Link& rLink ) // ----------------------------------------------------------------------- +void Application::EnableNoYieldMode( bool i_bNoYield ) +{ + ImplSVData* pSVData = ImplGetSVData(); + pSVData->maAppData.mbNoYield = i_bNoYield; +} + +// ----------------------------------------------------------------------- + +void Application::AddPostYieldListener( const Link& i_rListener ) +{ + ImplSVData* pSVData = ImplGetSVData(); + if( ! pSVData->maAppData.mpPostYieldListeners ) + pSVData->maAppData.mpPostYieldListeners = new VclEventListeners2(); + pSVData->maAppData.mpPostYieldListeners->addListener( i_rListener ); +} + +// ----------------------------------------------------------------------- + +void Application::RemovePostYieldListener( const Link& i_rListener ) +{ + ImplSVData* pSVData = ImplGetSVData(); + if( pSVData->maAppData.mpPostYieldListeners ) + pSVData->maAppData.mpPostYieldListeners->removeListener( i_rListener ); +} + +// ----------------------------------------------------------------------- + WorkWindow* Application::GetAppWindow() { return ImplGetSVData()->maWinData.mpAppWin; diff --git a/vcl/source/app/vclevent.cxx b/vcl/source/app/vclevent.cxx index 8ebc65c8a3f6..704d68c5bc7f 100644 --- a/vcl/source/app/vclevent.cxx +++ b/vcl/source/app/vclevent.cxx @@ -80,3 +80,56 @@ BOOL VclEventListeners::Process( VclSimpleEvent* pEvent ) const } return bProcessed; } + +VclEventListeners2::VclEventListeners2() +{ +} + +VclEventListeners2::~VclEventListeners2() +{ +} + +void VclEventListeners2::addListener( const Link& i_rLink ) +{ + // ensure uniqueness + for( std::list< Link >::const_iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it ) + { + if( *it == i_rLink ) + return; + } + m_aListeners.push_back( i_rLink ); +} + +void VclEventListeners2::removeListener( const Link& i_rLink ) +{ + size_t n = m_aIterators.size(); + for( size_t i = 0; i < n; i++ ) + { + if( m_aIterators[i].m_aIt != m_aListeners.end() && *m_aIterators[i].m_aIt == i_rLink ) + { + m_aIterators[i].m_bWasInvalidated = true; + ++m_aIterators[i].m_aIt; + } + } + m_aListeners.remove( i_rLink ); +} + +void VclEventListeners2::callListeners( VclSimpleEvent* i_pEvent ) +{ + vcl::DeletionListener aDel( this ); + + m_aIterators.push_back( ListenerIt() ); + size_t nIndex = m_aIterators.size() - 1; + m_aIterators[ nIndex ].m_aIt = m_aListeners.begin(); + while( ! aDel.isDeleted() && m_aIterators[ nIndex ].m_aIt != m_aListeners.end() ) + { + m_aIterators[ nIndex ].m_aIt->Call( i_pEvent ); + if( m_aIterators[ nIndex ].m_bWasInvalidated ) + // check if the current element was removed and the iterator increased in the meantime + m_aIterators[ nIndex ].m_bWasInvalidated = false; + else + ++m_aIterators[ nIndex ].m_aIt; + } + m_aIterators.pop_back(); +} + diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index d4fc6fa27117..dd2f4a62c88d 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -3615,6 +3615,7 @@ sal_Int32 PDFWriterImpl::emitFontDescriptor( const ImplFontData* pFont, FontSubs break; case FontSubsetInfo::TYPE1_PFA: case FontSubsetInfo::TYPE1_PFB: + case FontSubsetInfo::ANY_TYPE1: break; default: DBG_ERROR( "unknown fonttype in PDF font descriptor" ); diff --git a/vcl/source/gdi/regband.cxx b/vcl/source/gdi/regband.cxx index 938a30351f9a..09c97ef7cd2b 100644 --- a/vcl/source/gdi/regband.cxx +++ b/vcl/source/gdi/regband.cxx @@ -110,7 +110,7 @@ ImplRegionBand::ImplRegionBand( if ( ! bIgnorePoints) { // Copy points. - ImplRegionBandPoint* pPoint = mpFirstBandPoint; + ImplRegionBandPoint* pPoint = rRegionBand.mpFirstBandPoint; ImplRegionBandPoint* pPrevPointCopy = NULL; while (pPoint != NULL) { diff --git a/vcl/unx/headless/svppspgraphics.cxx b/vcl/unx/headless/svppspgraphics.cxx index 3e9d67bcbbe9..1311aaed4ee4 100644 --- a/vcl/unx/headless/svppspgraphics.cxx +++ b/vcl/unx/headless/svppspgraphics.cxx @@ -986,13 +986,6 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico return NULL; // fill in font info - switch( aFontInfo.m_eType ) - { - case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break; - case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break; - default: - return NULL; - } rInfo.m_nAscent = aFontInfo.m_nAscend; rInfo.m_nDescent = aFontInfo.m_nDescend; rInfo.m_aPSName = rMgr.getPSName( aFont ); @@ -1029,9 +1022,22 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico rInfo.m_nCapHeight = yMax; // Well ... for( int i = 0; i < 256; i++ ) - pWidths[i] = (aMetrics[i].width > 0 ? aMetrics[i].width : 0); + switch( aFontInfo.m_eType ) + { + case psp::fonttype::TrueType: + rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; + break; + case psp::fonttype::Type1: { + const bool bPFA = ((*(unsigned char*)pFile) < 0x80); + rInfo.m_nFontType = bPFA ? FontSubsetInfo::TYPE1_PFA : FontSubsetInfo::TYPE1_PFB; + } + break; + default: + return NULL; + } + return pFile; } diff --git a/vcl/unx/source/gdi/pspgraphics.cxx b/vcl/unx/source/gdi/pspgraphics.cxx index 009b14c56062..227d6cd7e9b2 100644 --- a/vcl/unx/source/gdi/pspgraphics.cxx +++ b/vcl/unx/source/gdi/pspgraphics.cxx @@ -1094,13 +1094,6 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico return NULL; // fill in font info - switch( aFontInfo.m_eType ) - { - case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break; - case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break; - default: - return NULL; - } rInfo.m_nAscent = aFontInfo.m_nAscend; rInfo.m_nDescent = aFontInfo.m_nDescend; rInfo.m_aPSName = rMgr.getPSName( aFont ); @@ -1137,9 +1130,22 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico rInfo.m_nCapHeight = yMax; // Well ... for( int i = 0; i < 256; i++ ) - pWidths[i] = (aMetrics[i].width > 0 ? aMetrics[i].width : 0); + switch( aFontInfo.m_eType ) + { + case psp::fonttype::TrueType: + rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; + break; + case psp::fonttype::Type1: { + const bool bPFA = ((*(unsigned char*)pFile) < 0x80); + rInfo.m_nFontType = bPFA ? FontSubsetInfo::TYPE1_PFA : FontSubsetInfo::TYPE1_PFB; + } + break; + default: + return NULL; + } + return pFile; } diff --git a/vcl/unx/source/gdi/salgdi.cxx b/vcl/unx/source/gdi/salgdi.cxx index 34f2dfd4b935..c09803dcb269 100644 --- a/vcl/unx/source/gdi/salgdi.cxx +++ b/vcl/unx/source/gdi/salgdi.cxx @@ -1028,11 +1028,12 @@ BOOL X11SalGraphics::drawEPS( long,long,long,long,void*,ULONG ) XID X11SalGraphics::GetXRenderPicture() { + XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); + if( !m_aRenderPicture ) { // check xrender support for matching visual // find a XRenderPictFormat compatible with the Drawable - XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat()); if( !pVisualFormat ) { @@ -1053,7 +1054,15 @@ XID X11SalGraphics::GetXRenderPicture() // TODO: avoid clipping if already set correctly if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) ) rRenderPeer.SetPictureClipRegion( aDstPic, pClipRegion_ ); + else #endif + { + // reset clip region + // TODO: avoid clip reset if already done + XRenderPictureAttributes aAttr; + aAttr.clip_mask = None; + rRenderPeer.ChangePicture( m_aRenderPicture, CPClipMask, &aAttr ); + } return m_aRenderPicture; } @@ -1096,6 +1105,7 @@ bool IsLeftOf( const XLineFixed& rA, const XLineFixed& rB ) const XFixed aXDiff = rU.p2.x - rU.p1.x; const XFixed aYDiff = rU.p2.y - rU.p1.y; + // compare upper point of lower segment with line through upper segment if( (rU.p1.y != rL.p1.y) || (rU.p1.x != rL.p1.x) ) { const sal_Int64 n1 = (sal_Int64)aXDiff * (rL.p1.y - rU.p1.y); @@ -1104,6 +1114,7 @@ bool IsLeftOf( const XLineFixed& rA, const XLineFixed& rB ) return ((n1 < n2) == bAbove); } + // compare lower point of lower segment with line through upper segment if( (rU.p2.y != rL.p2.y) || (rU.p2.x != rL.p2.x) ) { const sal_Int64 n3 = (sal_Int64)aXDiff * (rL.p2.y - rU.p1.y); @@ -1122,10 +1133,14 @@ struct HalfTrapezoid // maLine.p1.y <= mnY < maLine.p2.y XLineFixed maLine; XFixed mnY; + + XFixed getXMin() const { return std::min( maLine.p1.x, maLine.p2.x); } + XFixed getXMax() const { return std::max( maLine.p1.x, maLine.p2.x); } }; -struct HalfTrapCompare +class HalfTrapCompare { +public: bool operator()( const HalfTrapezoid& rA, const HalfTrapezoid& rB ) const { bool bIsTopLeft = false; @@ -1138,14 +1153,15 @@ struct HalfTrapCompare } }; -typedef std::priority_queue< HalfTrapezoid, std::vector<HalfTrapezoid>, HalfTrapCompare > HTQueueBase; +typedef std::vector< HalfTrapezoid > HTVector; +typedef std::priority_queue< HalfTrapezoid, HTVector, HalfTrapCompare > HTQueueBase; // we need a priority queue with a reserve() to prevent countless reallocations class HTQueue : public HTQueueBase { public: void reserve( size_t n ) { c.reserve( n ); } - int capacity() { return c.capacity(); } + void swapvec( HTVector& v ) { c.swap( v ); } }; typedef std::vector<XTrapezoid> TrapezoidVector; @@ -1173,6 +1189,10 @@ public: }; typedef std::multiset< int, TrapezoidYCompare > VerticalTrapSet; + +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND +void splitIntersectingSegments( HTVector&); +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND } // end of anonymous namespace // draw a poly-polygon @@ -1210,7 +1230,7 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // don't bother with polygons outside of visible area const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() ); const basegfx::B2DRange aPolyRange = basegfx::tools::getRange( rOrigPolyPoly ); - const bool bNeedViewClip = !aPolyRange.isInside( aViewRange ); + const bool bNeedViewClip = aPolyRange.isInside( aViewRange ); if( !aPolyRange.overlaps( aViewRange ) ) return true; @@ -1237,6 +1257,15 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly if( !nClippedPolyCount ) continue; +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND + for( int nClippedPolyIdx = 0; nClippedPolyIdx < nClippedPolyCount; ++nClippedPolyIdx ) + { + const ::basegfx::B2DPolygon aSolvedPolygon = aClippedPolygon.getB2DPolygon( nClippedPolyIdx ); + const int nPointCount = aSolvedPolygon.count(); + aGoodPolyPoly.append( aSolvedPolygon ); + nHTQueueReserve += aSolvedPolygon.areControlPointsUsed() ? 8 * nPointCount : nPointCount; + } +#else // DISABLE_SOLVECROSSOVER_WORKAROUND // #i103259# polypoly.solveCrossover() fails to remove self-intersections // but polygon.solveCrossover() works. Use it to build the intersection-free polypolygon // TODO: if the self-intersection prevention is too expensive make the trap-algorithm tolerate intersections @@ -1255,11 +1284,12 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly nHTQueueReserve += aSolvedPolygon.areControlPointsUsed() ? 8 * nPointCount : nPointCount; } } +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND } // #i100922# try to prevent priority-queue reallocations by reservering enough nHTQueueReserve = ((4*nHTQueueReserve) | 0x1FFF) + 1; - HTQueue aHTQueue; - aHTQueue.reserve( nHTQueueReserve ); + HTVector aHTVector; + aHTVector.reserve( nHTQueueReserve ); // first convert the B2DPolyPolygon to HalfTrapezoids const int nGoodPolyCount = aGoodPolyPoly.count(); @@ -1299,9 +1329,6 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // check if enough data is available for a new HalfTrapezoid if( nPointIdx == 0 ) continue; - // ignore vertical segments - if( aNewXPF.y == aOldXPF.y ) - continue; // construct HalfTrapezoid as topdown segment HalfTrapezoid aHT; @@ -1326,14 +1353,33 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly #endif // queue up the HalfTrapezoid - aHTQueue.push( aHT ); + aHTVector.push_back( aHT ); } } } - if( aHTQueue.empty() ) + if( aHTVector.empty() ) return TRUE; +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND + // find intersecting halftraps and split them up + // TODO: remove when solveCrossOvers gets fast enough so its use can be enabled above + // FAQ: why should segment intersection be handled before adaptiveSubdivide()? + // Answer: because it is conceptually much faster + // Example: consider two intersecting circles with a diameter of 1000 pixels + // before subdivision: eight bezier segments + // after subdivision: more than a thousand line segments + // since even the best generic intersection finders have a complexity of O((n+k)*log(n+k)) + // it shows that testing while the segment count is still low is a much better approach. + splitIntersectingSegments( aHTVector); +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND + + // build queue from vector of intersection-free segments + // TODO: is replacing the priority-queue by a sorted vector worth it? + std::make_heap( aHTVector.begin(), aHTVector.end(), HalfTrapCompare()); + HTQueue aHTQueue; + aHTQueue.swapvec( aHTVector); + // then convert the HalfTrapezoids into full Trapezoids TrapezoidVector aTrapVector; aTrapVector.reserve( aHTQueue.size() * 2 ); // just a guess @@ -1349,24 +1395,28 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly XTrapezoid aTrapezoid; // convert a HalfTrapezoid pair + // get the left side of the trapezoid const HalfTrapezoid& rLeft = aHTQueue.top(); aTrapezoid.top = rLeft.mnY; - aTrapezoid.bottom = rLeft.maLine.p2.y; aTrapezoid.left = rLeft.maLine; + aHTQueue.pop(); -#if 0 - // ignore empty trapezoids - if( aTrapezoid.bottom <= aTrapezoid.top ) + // ignore left segment that would result in an empty trapezoid + if( aTrapezoid.left.p2.y <= aTrapezoid.top ) continue; -#endif - aHTQueue.pop(); - if( aHTQueue.empty() ) // TODO: assert - break; - const HalfTrapezoid& rRight = aHTQueue.top(); - aTrapezoid.right = rRight.maLine; - aHTQueue.pop(); + // get the right side of the trapezoid + aTrapezoid.right.p2.y = aTrapezoid.bottom; + while( !aHTQueue.empty() ) { + const HalfTrapezoid& rRight = aHTQueue.top(); + aTrapezoid.right = rRight.maLine; + aHTQueue.pop(); + // ignore right segment that would result in an empty trapezoid + if( aTrapezoid.right.p2.y > aTrapezoid.top ) + break; + } + // the topmost endpoint determines the trapezoid bottom aTrapezoid.bottom = aTrapezoid.left.p2.y; if( aTrapezoid.bottom > aTrapezoid.right.p2.y ) aTrapezoid.bottom = aTrapezoid.right.p2.y; @@ -1374,44 +1424,49 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // keep the full Trapezoid candidate aTrapVector.push_back( aTrapezoid ); - // unless it splits an older trapezoid + // unless it splits another trapezoid that is still active bool bSplit = false; - for(;;) + ActiveTrapSet::iterator aActiveTrapsIt = aActiveTraps.begin(); + for(; aActiveTrapsIt != aActiveTraps.end(); ++aActiveTrapsIt ) { - // check if the new trapezoid overlaps with an old trapezoid - ActiveTrapSet::iterator aActiveTrapsIt - = aActiveTraps.upper_bound( aTrapVector.size()-1 ); - if( aActiveTrapsIt == aActiveTraps.begin() ) - break; - --aActiveTrapsIt; - XTrapezoid& rLeftTrap = aTrapVector[ *aActiveTrapsIt ]; + // skip until first overlap candidate + // TODO: use stl::*er_bound() instead + if( IsLeftOf( aTrapezoid.left, rLeftTrap.left) ) + continue; + // in the ActiveTrapSet there are still trapezoids where // a vertical overlap with new trapezoids is no longer possible // they could have been removed in the verticaltraps loop below - // but this would have been expensive and is not needed as we can - // simply ignore them now and remove them from the ActiveTrapSet - // so they won't bother us in the future + // but this would be expensive and is not needed as we can + // simply ignore them until we stumble upon them here. if( rLeftTrap.bottom <= aTrapezoid.top ) { - aActiveTraps.erase( aActiveTrapsIt ); + ActiveTrapSet::iterator it = aActiveTrapsIt; + if( aActiveTrapsIt != aActiveTraps.begin() ) + --aActiveTrapsIt; + aActiveTraps.erase( it ); continue; } // check if there is horizontal overlap // aTrapezoid.left==rLeftTrap.right is allowed though if( !IsLeftOf( aTrapezoid.left, rLeftTrap.right ) ) - break; + continue; - // split the old trapezoid and keep its upper part + // prepare to split the old trapezoid and keep its upper part // find the old trapezoids entry in the VerticalTrapSet and remove it typedef std::pair<VerticalTrapSet::iterator, VerticalTrapSet::iterator> VTSPair; VTSPair aVTSPair = aVerticalTraps.equal_range( *aActiveTrapsIt ); VerticalTrapSet::iterator aVTSit = aVTSPair.first; - for(; (aVTSit != aVTSPair.second) && (*aVTSit != *aActiveTrapsIt); ++aVTSit ) ; - if( aVTSit != aVTSPair.second ) + for(; aVTSit != aVTSPair.second; ++aVTSit ) + { + if( *aVTSit != *aActiveTrapsIt ) + continue; aVerticalTraps.erase( aVTSit ); + break; + } // then update the old trapezoid's bottom rLeftTrap.bottom = aTrapezoid.top; // enter the updated old trapzoid in VerticalTrapSet @@ -1444,24 +1499,26 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // mark trapezoids that can no longer be split as inactive // and recycle their sides which were not fully resolved static const XFixed nMaxTop = +0x7FFFFFFF; - XFixed nNewTop = aHTQueue.empty() ? nMaxTop : aHTQueue.top().mnY; + const XFixed nNewTop = aHTQueue.empty() ? nMaxTop : aHTQueue.top().mnY; while( !aVerticalTraps.empty() ) { + // check the next trapezoid to be retired const XTrapezoid& rOldTrap = aTrapVector[ *aVerticalTraps.begin() ]; if( nNewTop < rOldTrap.bottom ) break; - // the reference Trapezoid can no longer be split + // this trapezoid can no longer be split aVerticalTraps.erase( aVerticalTraps.begin() ); // recycle its sides that were not fully resolved HalfTrapezoid aHT; aHT.mnY = rOldTrap.bottom; - if( rOldTrap.left.p2.y > rOldTrap.bottom ) + + if( rOldTrap.left.p2.y > aHT.mnY ) { aHT.maLine = rOldTrap.left; aHTQueue.push( aHT ); } - if( rOldTrap.right.p2.y > rOldTrap.bottom ) + if( rOldTrap.right.p2.y > aHT.mnY ) { aHT.maLine = rOldTrap.right; aHTQueue.push( aHT ); @@ -1527,13 +1584,20 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const : aPolygon.transform( aAnisoMatrix ); } - // AW: reSegment no longer needed; new createAreaGeometry will remove exteme positions - // and create bezier polygons - //if( aPolygon.areControlPointsUsed() ) - // aPolygon = basegfx::tools::reSegmentPolygonEdges( aPolygon, 8, true, false ); - //const basegfx::B2DPolyPolygon aAreaPolyPoly = basegfx::tools::createAreaGeometryForSimplePolygon( - // aPolygon, 0.5*rLineWidth.getX(), eLineJoin ); - const basegfx::B2DPolyPolygon aAreaPolyPoly(basegfx::tools::createAreaGeometry(aPolygon, 0.5*rLineWidth.getX(), eLineJoin)); + // special handling for hairlines to improve the drawing performance + // TODO: revisit after basegfx performance related changes + const bool bIsHairline = (rLineWidth.getX() < 1.2) && (rLineWidth.getY() < 1.2); + if( bIsHairline ) + { + // for hairlines the linejoin style becomes irrelevant + eLineJoin = basegfx::B2DLINEJOIN_NONE; + // createAreaGeometry is still too expensive when beziers are involved + if( aPolygon.areControlPointsUsed() ) + aPolygon = ::basegfx::tools::adaptiveSubdivideByDistance( aPolygon, 0.125 ); + } + + // create the area-polygon for the line + const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, 0.5*rLineWidth.getX(), eLineJoin) ); if( (rLineWidth.getX() != rLineWidth.getY()) && !basegfx::fTools::equalZero( rLineWidth.getX() ) ) @@ -1568,3 +1632,259 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND +// TODO: move the intersection solver into basegfx +// and then support bezier-intersection finding too + +namespace { // anonymous namespace to prevent export + +typedef HalfTrapezoid LineSeg; +typedef HTVector LSVector; + +inline bool operator==( const LineSeg& r1, const LineSeg& r2) +{ + if( r1.maLine.p2.y != r2.maLine.p2.y) return false; + if( r1.maLine.p2.x != r2.maLine.p2.x) return false; + if( r1.maLine.p1.y != r2.maLine.p1.y) return false; + if( r1.maLine.p1.x != r2.maLine.p1.x) return false; + return true; +} + +struct LSYMinCmp +{ + bool operator()( const LineSeg& r1, const LineSeg& r2) const + { return r2.maLine.p1.y < r1.maLine.p1.y; } +}; + +struct LSYMaxCmp +{ + bool operator()( const LineSeg& r1, const LineSeg& r2) const + { return r2.maLine.p2.y < r1.maLine.p2.y; } +}; + +struct LSXMinCmp +{ + bool operator()( const LineSeg& r1, const LineSeg& r2) const + { return( r1.getXMin() < r2.getXMin()); } +}; + +struct CutPoint +{ + XFixed mnSegmentId; + float mfCutParam; + XPointFixed maPoint; +}; + +struct CutPointCmp +{ + bool operator()( const CutPoint& r1, const CutPoint& r2) const + { + if( r1.mnSegmentId != r2.mnSegmentId) + return (r1.mnSegmentId < r2.mnSegmentId); + return (r1.mfCutParam < r2.mfCutParam); + } +}; + +bool findIntersection( const LineSeg& rLS1, const LineSeg& rLS2, CutPoint aCutPoints[2]) +{ + // segments intersect at r1.p1 + s*(r1.p2-r1.p1) == r2.p1 + t*(r2.p2-r2.p1) + // when both segment-parameters are ((0 <s<1) && (0<t<1)) + // (r1.p1 - r2.p1) == s * (r1.p1 - r1.p2) + t * (r2.p2 - r2.p1) + // => + // (r1.p1x - r2.p1x) == s * (r1.p1x - r1.p2x) + t * (r2.p2x - r2.p1x) + // (r1.p1y - r2.p1y) == s * (r1.p1y - r1.p2y) + t * (r2.p2y - r2.p1y) + // check if lines are identical or parallel => not intersecting + const XLineFixed& r1 = rLS1.maLine; + const XLineFixed& r2 = rLS2.maLine; + const double fDet = (double)(r1.p1.x - r1.p2.x) * (r2.p2.y - r2.p1.y) + - (double)(r2.p2.x - r2.p1.x) * (r1.p1.y - r1.p2.y); + static const double fEps = 1e-8; + if( fabs(fDet) < fEps) + return false; + // check if intersecting with first segment + const double fS1 = (double)(r2.p2.y - r2.p1.y) * (r1.p1.x - r2.p1.x); + const double fS2 = (double)(r2.p2.x - r2.p1.x) * (r2.p1.y - r1.p1.y); + const double fS = (fS1 + fS2) / fDet; + if( (fS <= +fEps) || (fS >= 1-fEps)) + return false; + // check if intersecting with second segment + const double fT1 = (double)(r1.p2.y - r1.p1.y) * (r1.p1.x - r2.p1.x); + const double fT2 = (double)(r1.p2.x - r1.p1.x) * (r2.p1.y - r1.p1.y); + const double fT = (fT1 + fT2) / fDet; + if( (fT <= +fEps) || (fT >= 1-fEps)) + return false; + // force the intersection point to be exactly identical on both segments + aCutPoints[0].maPoint.x = (XFixed)(r1.p1.x + fS * (r1.p2.x - r1.p1.x)); + aCutPoints[0].maPoint.y = (XFixed)(r1.p1.y + fS * (r1.p2.y - r1.p1.y)); + aCutPoints[1].maPoint.x = aCutPoints[0].maPoint.x; + aCutPoints[1].maPoint.y = aCutPoints[0].maPoint.y; + aCutPoints[0].mnSegmentId = rLS1.mnY; + aCutPoints[0].mfCutParam = (float)fS; + aCutPoints[1].mnSegmentId = rLS2.mnY; + aCutPoints[1].mfCutParam = (float)fT; + return true; +} + +typedef std::priority_queue< LineSeg, LSVector, LSYMinCmp> LSYMinQueueBase; +typedef std::priority_queue< LineSeg, LSVector, LSYMaxCmp> LSYMaxQueueBase; +typedef std::multiset< LineSeg, LSXMinCmp> LSXMinSet; +typedef std::set< CutPoint, CutPointCmp> CutPointSet; + +class LSYMinQueue : public LSYMinQueueBase +{ +public: + void reserve( size_t n) { c.reserve(n);} + void swapvec( LSVector& v) { c.swap(v);} +}; + +class LSYMaxQueue : public LSYMaxQueueBase +{ +public: + void reserve( size_t n) { c.reserve(n);} +}; + +void addAndCutSegment( LSVector& rLSVector, const LineSeg& rLS, CutPointSet& rCutPointSet) +{ + // short circuit when no segment was cut + if( rCutPointSet.empty()) { + rLSVector.push_back( rLS); + return; + } + + // find the first cut point for this segment + LineSeg aCS = rLS; + CutPoint aMinCutPoint; + aMinCutPoint.mnSegmentId = rLS.mnY; + aMinCutPoint.mfCutParam = 0.0; + CutPointSet::iterator itFirst = rCutPointSet.lower_bound( aMinCutPoint); + CutPointSet::iterator it = itFirst; + // iterate through all cut points of this segment + for(; it != rCutPointSet.end(); ++it) { + const CutPoint rCutPoint = (*it); + if( rCutPoint.mnSegmentId != rLS.mnY) + break; + // cut segment at the cutpoint + aCS.maLine.p2 = rCutPoint.maPoint; + rLSVector.push_back( aCS); + // prepare for next segment cut + aCS.maLine.p1 = aCS.maLine.p2; + } + // remove cutparams that will no longer be needed + // TODO: is it worth it or should we just keep the cutparams? + rCutPointSet.erase( itFirst, it); + + // add segment part remaining after last cut + aCS.maLine.p2 = rLS.maLine.p2; + rLSVector.push_back( aCS); +} + +void splitIntersectingSegments( LSVector& rLSVector) +{ + // get a unique id for each lineseg, temporarily abuse the mnY member + LSVector::iterator aLSit = rLSVector.begin(); + for( int i = 0; aLSit != rLSVector.end(); ++aLSit) { + LineSeg& rLS = *aLSit; + rLS.mnY = i++; + } + // get an y-sorted queue from the input vector + LSYMinQueue aYMinQueue; + std::make_heap( rLSVector.begin(), rLSVector.end(), LSYMinCmp()); + aYMinQueue.swapvec( rLSVector); + + // prepare the result vector + // try to avoid reallocations by guessing a reasonable result size + rLSVector.reserve( aYMinQueue.size() * 1.5); + + // find all intersections + CutPointSet aCutPointSet; + LSXMinSet aXMinSet; + LSYMaxQueue aYMaxQueue; + aYMaxQueue.reserve( aYMinQueue.size()); + // sweep-down and check all segment-pairs that overlap + while( !aYMinQueue.empty()) { + // get next input-segment + const LineSeg& rLS = aYMinQueue.top(); + // retire obsoleted segments + const XFixed fYCur = rLS.maLine.p1.y; + while( !aYMaxQueue.empty()) { + // check next segment to be retired + const LineSeg& rOS = aYMaxQueue.top(); + if( fYCur < rOS.maLine.p2.y) + break; + // emit resolved segment into result + addAndCutSegment( rLSVector, rOS, aCutPointSet); + // find segment to be retired in xmin-compare-set + LSXMinSet::iterator itR = aXMinSet.lower_bound( rOS); + while( !(*itR == rOS)) ++itR; + // retire segment from xmin-compare-set + aXMinSet.erase( itR); + // this segment is pining for the fjords + aYMaxQueue.pop(); + } + + // iterate over all segments that might overlap + // skip over the leftmost segments that cannot overlap + const XFixed fXMax = rLS.getXMax(); + LSXMinSet::const_iterator itC = aXMinSet.begin(); + for(; itC != aXMinSet.end(); ++itC) + if( (*itC).getXMin() <= fXMax) + break; + // TODO: if the linear search becomes too expensive + // then use an XMaxQueue based approach to replace it + const XFixed fXMin = rLS.getXMin(); + for(; itC != aXMinSet.end(); ++itC) { + const LineSeg& rOS = *itC; + if( fXMin >= rOS.getXMax()) + continue; + if( fXMax < rOS.getXMin()) + break; + CutPoint aCutPoints[2]; + if( !findIntersection( rLS, rOS, aCutPoints)) + continue; + // remember cut parameters + // TODO: std::set seems to use individual allocations + // which results in perf-problems for many entries + // => pre-allocate nodes by using a non-default allocator + aCutPointSet.insert( aCutPoints[0]); + aCutPointSet.insert( aCutPoints[1]); + } + // add segment to xmin-compare-set + // TODO: do we have a good insertion hint? + aXMinSet.insert( /*itC,*/ rLS); + // register segment for retirement + aYMaxQueue.push( rLS); + aYMinQueue.pop(); + } + + // retire the remaining segments + aXMinSet.clear(); + while( !aYMaxQueue.empty()) { + // emit segments and cut them up if needed + const LineSeg& rLS = aYMaxQueue.top(); + addAndCutSegment( rLSVector, rLS, aCutPointSet); + aYMaxQueue.pop(); + } + + // get the segments ready to be consumed by the drawPolygon() caller + aLSit = rLSVector.begin(); + LSVector::iterator aLSit2 = aLSit; + for(; aLSit != rLSVector.end(); ++aLSit) { + LineSeg& rLS = *aLSit; + // restore the segment top member + rLS.mnY = rLS.maLine.p1.y; + // remove horizontal segments for now + // TODO: until the trapezoid converter is adjusted to handle them + if( rLS.maLine.p1.y == rLS.maLine.p2.y ) + continue; + *(aLSit2++) = rLS; + } + if(aLSit2 != aLSit) + rLSVector.resize( aLSit2 - rLSVector.begin() ); +} + +} // end anonymous namespace + +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + diff --git a/vcl/unx/source/gdi/xrender_peer.cxx b/vcl/unx/source/gdi/xrender_peer.cxx index d8f2045c6fde..fc8de818fafd 100644 --- a/vcl/unx/source/gdi/xrender_peer.cxx +++ b/vcl/unx/source/gdi/xrender_peer.cxx @@ -142,6 +142,10 @@ void XRenderPeer::InitRenderLib() mpXRenderCreatePicture = (Picture(*)(Display*,Drawable,const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*))pFunc; + pFunc = osl_getAsciiFunctionSymbol( mpRenderLib, "XRenderChangePicture" ); + if( !pFunc ) return; + mpXRenderChangePicture = (void(*)(Display*,Picture,unsigned long,const XRenderPictureAttributes*))pFunc; + pFunc = osl_getAsciiFunctionSymbol( mpRenderLib, "XRenderSetPictureClipRegion" ); if( !pFunc ) return; mpXRenderSetPictureClipRegion = (void(*)(Display*,Picture,XLIB_Region))pFunc; diff --git a/vcl/unx/source/gdi/xrender_peer.hxx b/vcl/unx/source/gdi/xrender_peer.hxx index f1e2fd77a273..27c8fb3dcaeb 100644 --- a/vcl/unx/source/gdi/xrender_peer.hxx +++ b/vcl/unx/source/gdi/xrender_peer.hxx @@ -66,6 +66,8 @@ public: const XRenderPictFormat& ) const; Picture CreatePicture( Drawable, const XRenderPictFormat*, unsigned long nDrawable, const XRenderPictureAttributes* ) const; + void ChangePicture( Picture, unsigned long nValueMask, + const XRenderPictureAttributes* ) const; void SetPictureClipRegion( Picture, XLIB_Region ) const; void CompositePicture( int nOp, Picture aSrc, Picture aMask, Picture aDst, int nXSrc, int nYSrc, int nXMask, int nYMask, @@ -103,6 +105,8 @@ private: Picture (*mpXRenderCreatePicture)(Display*,Drawable, const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*); + void (*mpXRenderChangePicture)(Display*,Picture, + unsigned long,const XRenderPictureAttributes*); void (*mpXRenderSetPictureClipRegion)(Display*,Picture,XLIB_Region); void (*mpXRenderFreePicture)(Display*,Picture); void (*mpXRenderComposite)(Display*,int,Picture,Picture,Picture, @@ -194,6 +198,16 @@ inline Picture XRenderPeer::CreatePicture( Drawable aDrawable, #endif } +inline void XRenderPeer::ChangePicture( Picture aPicture, + unsigned long nValueMask, const XRenderPictureAttributes* pRenderAttr ) const +{ +#ifdef XRENDER_LINK + XRenderChangePicture( mpDisplay, aPicture, nValueMask, pRenderAttr ); +#else + (*mpXRenderChangePicture)( mpDisplay, aPicture, nValueMask, pRenderAttr ); +#endif +} + inline void XRenderPeer::SetPictureClipRegion( Picture aPicture, XLIB_Region aXlibRegion ) const { diff --git a/vcl/unx/source/printergfx/common_gfx.cxx b/vcl/unx/source/printergfx/common_gfx.cxx index 632f0d70aa2f..9b305ff323ba 100644 --- a/vcl/unx/source/printergfx/common_gfx.cxx +++ b/vcl/unx/source/printergfx/common_gfx.cxx @@ -7,7 +7,6 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: common_gfx.cxx,v $ - * $Revision: 1.20.18.1 $ * * This file is part of OpenOffice.org. * @@ -535,68 +534,47 @@ PrinterGfx::DrawPolyLineBezier (sal_uInt32 nPoints, const Point* pPath, const BY const sal_uInt32 nBezString = 1024; sal_Char pString[nBezString]; - if ( maLineColor.Is() && nPoints && pPath ) + if ( nPoints > 1 && maLineColor.Is() && pPath ) { PSSetColor (maLineColor); PSSetColor (); PSSetLineWidth (); - if (pFlgAry[0] != POLY_NORMAL) //There must be a starting point to moveto - { - return; - } - else - { - snprintf(pString, nBezString, "%li %li moveto\n", pPath[0].X(), pPath[0].Y()); - WritePS(mpPageBody, pString); - } + snprintf(pString, nBezString, "%li %li moveto\n", pPath[0].X(), pPath[0].Y()); + WritePS(mpPageBody, pString); // Handle the drawing of mixed lines mixed with curves // - a normal point followed by a normal point is a line // - a normal point followed by 2 control points and a normal point is a curve for (unsigned int i=1; i<nPoints;) { - if (pFlgAry[i+1] != POLY_CONTROL) //If the next point is a POLY_NORMAL, we're drawing a line + if (pFlgAry[i] != POLY_CONTROL) //If the next point is a POLY_NORMAL, we're drawing a line { - if (i+1 >= nPoints) return; //Make sure we don't pass the end of the array snprintf(pString, nBezString, "%li %li lineto\n", pPath[i].X(), pPath[i].Y()); i++; } else //Otherwise we're drawing a spline { - if (i+3 >= nPoints) return; //Make sure we don't pass the end of the array - snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n", - pPath[i+1].X(), pPath[i+1].Y(), - pPath[i+2].X(), pPath[i+2].Y(), - pPath[i+3].X(), pPath[i+3].Y()); + if (i+2 >= nPoints) + return; //Error: wrong sequence of contol/normal points somehow + if ((pFlgAry[i] == POLY_CONTROL) && (pFlgAry[i+1] == POLY_CONTROL) && + (pFlgAry[i+2] != POLY_CONTROL)) + { + snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n", + pPath[i].X(), pPath[i].Y(), + pPath[i+1].X(), pPath[i+1].Y(), + pPath[i+2].X(), pPath[i+2].Y()); + } + else + { + DBG_ERROR( "PrinterGfx::DrawPolyLineBezier: Strange output" ); + } i+=3; } WritePS(mpPageBody, pString); } - } - - // if eofill and stroke, save the current path - if( maFillColor.Is() && maLineColor.Is()) - PSGSave(); - - // first draw area - if( maFillColor.Is() ) - { - PSSetColor (maFillColor); - PSSetColor (); - WritePS (mpPageBody, "eofill\n"); - } - - // restore the current path - if( maFillColor.Is() && maLineColor.Is()) - PSGRestore(); - // now draw outlines - if( maLineColor.Is() ) - { - PSSetColor (maLineColor); - PSSetColor (); - PSSetLineWidth (); + // now draw outlines WritePS (mpPageBody, "stroke\n"); } } @@ -635,7 +613,7 @@ PrinterGfx::DrawPolygonBezier (sal_uInt32 nPoints, const Point* pPath, const BYT } else { - fprintf(stderr, "Strange output\n"); + DBG_ERROR( "PrinterGfx::DrawPolygonBezier: Strange output" ); } i+=3; } @@ -699,9 +677,7 @@ PrinterGfx::DrawPolyPolygonBezier (sal_uInt32 nPoly, const sal_uInt32 * pPoints, } else { -#if OSL_DEBUG_LEVEL > 1 - fprintf(stderr, "Strange output\n"); -#endif + DBG_ERROR( "PrinterGfx::DrawPolyPolygonBezier: Strange output" ); } j+=3; } diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx index 73f4d8320acc..d82830a9022f 100644 --- a/vcl/win/source/gdi/salgdi3.cxx +++ b/vcl/win/source/gdi/salgdi3.cxx @@ -557,7 +557,7 @@ static ImplDevFontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXA& rE if( 0 != (rMetric.ntmFlags & (NTM_TT_OPENTYPE | NTM_PS_OPENTYPE)) || 0 != (rMetric.tmPitchAndFamily & TMPF_TRUETYPE)) aDFA.mbSubsettable = true; - else if( 0 != (rMetric.tmPitchAndFamily & NTM_TYPE1) ) // TODO: implement subsetting for type1 too + else if( 0 != (rMetric.ntmFlags & NTM_TYPE1) ) // TODO: implement subsetting for type1 too aDFA.mbEmbeddable = true; // heuristics for font quality @@ -636,7 +636,7 @@ static ImplDevFontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXW& rE if( 0 != (rMetric.ntmFlags & (NTM_TT_OPENTYPE | NTM_PS_OPENTYPE)) || 0 != (rMetric.tmPitchAndFamily & TMPF_TRUETYPE)) aDFA.mbSubsettable = true; - else if( 0 != (rMetric.tmPitchAndFamily & NTM_TYPE1) ) // TODO: implement subsetting for type1 too + else if( 0 != (rMetric.ntmFlags & NTM_TYPE1) ) // TODO: implement subsetting for type1 too aDFA.mbEmbeddable = true; // heuristics for font quality @@ -2162,7 +2162,7 @@ void WinSalGraphics::GetDevFontList( ImplDevFontList* pFontList ) ::rtl::OUString aExecutableFile( aPath ); aPath = aPath.copy( 0, aPath.lastIndexOf('/') ); String aFontDirUrl = aPath.copy( 0, aPath.lastIndexOf('/') ); - aFontDirUrl += String( RTL_CONSTASCII_USTRINGPARAM("/share/fonts/truetype") ); + aFontDirUrl += String( RTL_CONSTASCII_USTRINGPARAM("/Basis/share/fonts/truetype") ); // collect fonts in font path that could not be registered osl::Directory aFontDir( aFontDirUrl ); @@ -2723,7 +2723,8 @@ const void* WinSalGraphics::GetEmbedFontData( const ImplFontData* pFont, TEXTMETRICA aTm; if( !::GetTextMetricsA( mhDC, &aTm ) ) *pDataLen = 0; - rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; + const bool bPFA = (*aRawFontData.get() < 0x80); + rInfo.m_nFontType = bPFA ? FontSubsetInfo::TYPE1_PFA : FontSubsetInfo::TYPE1_PFB; WCHAR aFaceName[64]; int nFNLen = ::GetTextFaceW( mhDC, 64, aFaceName ); // #i59854# strip eventual null byte |