diff options
author | Release Engineers <releng@openoffice.org> | 2009-08-26 13:11:27 +0000 |
---|---|---|
committer | Release Engineers <releng@openoffice.org> | 2009-08-26 13:11:27 +0000 |
commit | 27a1e85b656bad222f113f650b03397aa3bc59d3 (patch) | |
tree | fac68d7fa88bffbbb938326923bd280d4992e2b1 /svtools | |
parent | a002f6d0433ef40e9a5fc16f6cf41818adced3ad (diff) |
CWS-TOOLING: integrate CWS gridcontrol_01
2009-08-13 07:53:28 +0200 tkr r274919 : #103210# remove mixed-line-endings
2009-08-13 07:36:19 +0200 tkr r274918 : #103210# remove mixed-line-endings
2009-08-06 14:02:11 +0200 tkr r274725 : #103210# build issues fixed
2009-08-06 12:11:52 +0200 tkr r274711 : #103210# build issues fixed
2009-08-06 12:03:32 +0200 tkr r274710 : #103210# add grid directory to d.lst
2009-08-05 17:00:11 +0200 misheto r274689 : CWS-TOOLING: rebase CWS gridcontrol_01 to trunk@274622 (milestone: DEV300:m54)
2009-08-05 14:31:42 +0200 tkr r274668 : #103210# remove add/removeMouseListener from XGridControl and use XWindow
2009-08-05 14:30:06 +0200 tkr r274667 : #103210# remove add/removeMouseListener from XGridControl and use XWindow
2009-08-05 14:29:09 +0200 tkr r274666 : #103210# remove add/removeMouseListener from XGridControl and use XWindow
2009-08-05 12:02:15 +0200 misheto r274649 : fox for HScroll problem
2009-08-05 11:37:22 +0200 misheto r274644 : CWS-TOOLING: rebase CWS gridcontrol_01 to trunk@274203 (milestone: DEV300:m53)
2009-08-03 10:12:50 +0200 tkr r274568 : #103210# Method getItemIndexPos() added
2009-07-31 18:25:42 +0200 misheto r274547 : fixed bug no cursor with NONE-selection, arrow keys cause selection disappear
2009-07-31 16:36:34 +0200 tkr r274541 : #103210# MouseListener added
2009-07-31 16:35:48 +0200 tkr r274540 : #103210# MouseListener added
2009-07-31 14:37:45 +0200 misheto r274533 : event handlers
2009-07-31 09:43:52 +0200 tkr r274513 : #103210# MouseListener added
2009-07-31 09:42:46 +0200 tkr r274512 : #103210# MouseListenerMultiplexer exported
2009-07-30 18:19:55 +0200 misheto r274501 : 2009-07-30 18:15:00 +0200 misheto r274500 : mouselistener changes
2009-07-30 15:23:03 +0200 tkr r274491 : #i103210# remove XItemListener and add XMouseListener
2009-07-30 15:22:01 +0200 tkr r274490 : #i103210# remove XItemListener and add XMouseListener
2009-07-28 16:47:37 +0200 misheto r274415 : fixed text left intented, removeAllScroll mode, selection mode, single selection
2009-07-28 16:45:32 +0200 misheto r274413 : 2009-07-28 14:56:33 +0200 tkr r274407 : #i103210# build issue fixed
2009-07-28 12:49:23 +0200 tkr r274397 : #i103210# use HScroll and VScroll for Scrolbarmode
2009-07-28 12:24:14 +0200 tkr r274396 : #i103210# use HScroll and VScroll for Scrolbarmode
2009-07-28 11:33:46 +0200 tkr r274393 : ##i103210# api changes
2009-07-28 11:32:48 +0200 tkr r274392 : ##i103210# add ItemListener
2009-07-28 11:31:49 +0200 tkr r274391 : ##i103210# add ItemListener
2009-07-28 08:30:30 +0200 tkr r274388 : #i103210# paint background color
2009-07-24 17:22:10 +0200 misheto r274314 : focus problem solved, single selection with keys UP DOWN
2009-07-22 11:43:24 +0200 misheto r274226 : removed vclxcontrol dependencies
2009-07-22 10:23:34 +0200 misheto r274220 : 2009-07-21 15:04:26 +0200 misheto r274200 : tablecontrol added items
2009-07-21 15:00:44 +0200 misheto r274198 : tablecontrol
2009-07-17 09:58:59 +0200 misheto r274082 : changes mihaela
2009-07-15 11:04:27 +0200 tkr r273999 : #i103210# api documentation added
2009-07-15 11:03:18 +0200 tkr r273998 : #i103210# adapt idl changes
2009-07-14 08:47:32 +0200 tkr r273959 : #i103210# Method removeRow added
2009-07-14 08:46:52 +0200 tkr r273958 : #i103210# Method removeRow added
2009-07-13 08:20:11 +0200 tkr r273914 : #i103210# XGridSelectionModel removed
2009-07-10 13:50:01 +0200 tkr r273888 : #i103210# selection support and listener added
2009-07-10 13:42:17 +0200 tkr r273887 : #i103210# selection support added
2009-07-06 10:21:51 +0200 tkr r273724 : #i103210# implement listener
2009-07-06 10:13:25 +0200 tkr r273723 : #i103210# remove wrong interfaces
2009-07-06 10:11:47 +0200 tkr r273722 : #i103210# interface changes
2009-07-02 15:28:50 +0200 tkr r273659 : #i103210# create new services
2009-07-02 15:26:21 +0200 tkr r273658 : #i103210# create new services
2009-07-02 12:00:39 +0200 tkr r273633 : #i103210# defaultgriddatamodel works now
2009-07-02 11:59:24 +0200 tkr r273631 : #i103210# now XGridDataModel inherits XComponent
2009-07-01 14:07:31 +0200 tkr r273579 : #i103210# initial implementation of the grid control data model
2009-07-01 13:14:21 +0200 tkr r273571 : #i103210# adding new service and some methods
2009-06-30 12:15:13 +0200 tkr r273500 : #i103210# change attribute names
2009-06-30 10:55:07 +0200 tkr r273496 : #i103210# create services and interfaces for the grid control
2009-06-30 10:47:26 +0200 tkr r273495 : #i103210# create services and interfaces for the grid control
Diffstat (limited to 'svtools')
26 files changed, 5812 insertions, 5 deletions
diff --git a/svtools/inc/svtools/table/abstracttablecontrol.hxx b/svtools/inc/svtools/table/abstracttablecontrol.hxx new file mode 100644 index 000000000000..03bc0a999f7a --- /dev/null +++ b/svtools/inc/svtools/table/abstracttablecontrol.hxx @@ -0,0 +1,130 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_ABSTRACTTABLECONTROL_HXX +#define SVTOOLS_INC_TABLE_ABSTRACTTABLECONTROL_HXX + +#include <sal/types.h> +#include <vcl/event.hxx> +#include <vcl/seleng.hxx> +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + enum TableControlAction + { + /// moves the cursor in the table control one row up, if possible, by keeping the current column + cursorUp, + /// moves the cursor in the table control one row down, if possible, by keeping the current column + cursorDown, + /// moves the cursor in the table control one column to the left, if possible, by keeping the current row + cursorLeft, + /// moves the cursor in the table control one column to the right, if possible, by keeping the current row + cursorRight, + /// moves the cursor to the beginning of the current line + cursorToLineStart, + /// moves the cursor to the end of the current line + cursorToLineEnd, + /// moves the cursor to the first row, keeping the current column + cursorToFirstLine, + /// moves the cursor to the last row, keeping the current column + cursorToLastLine, + /// moves the cursor one page up, keeping the current column + cursorPageUp, + /// moves the cursor one page down, keeping the current column + cursorPageDown, + /// moves the cursor to the top-most, left-most cell + cursorTopLeft, + /// moves the cursor to the bottom-most, right-most cell + cursorBottomRight, + /// selects the row, where the actual cursor is + cursorSelectRow, + /// selects the rows, above the actual cursor is + cursorSelectRowUp, + /// selects the row, beneath the actual cursor is + cursorSelectRowDown, + /// selects the row, from the actual cursor till top + cursorSelectRowAreaTop, + /// selects the row, from the actual cursor till bottom + cursorSelectRowAreaBottom, + + + /// invalid and final enumeration value, not to be actually used + invalidTableControlAction + }; + + //==================================================================== + //= IAbstractTableControl + //==================================================================== + /** defines a callback interface to be implemented by a concrete table control + */ + class SAL_NO_VTABLE IAbstractTableControl + { + public: + /** hides the cell cursor + + The method cares for successive calls, that is, for every call to + ->hideCursor(), you need one call to ->showCursor. Only if the number + of both calls matches, the cursor is really shown. + + @see showCursor + */ + virtual void hideCursor() = 0; + + /** shows the cell cursor + + @see hideCursor + */ + virtual void showCursor() = 0; + + /** dispatches an action to the table control + + @return + <TRUE/> if the action could be dispatched successfully, <FALSE/> otherwise. Usual + failure conditions include some other instance vetoing the action, or impossibility + to execute the action at all (for instance moving up one row when already positioned + on the very first row). + + @see TableControlAction + */ + virtual bool dispatchAction( TableControlAction _eAction ) = 0; + /** to be called on mouse button up/down + @return + <TRUE/> if the click was in the visible area of the table control, + <FALSE/> otherwise.*/ + virtual bool isClickInVisibleArea( const Point& _rPoint ) = 0; + /** returns selection engine*/ + virtual SelectionEngine* getSelEngine() = 0; + virtual void setCursorAtCurrentCell(const Point& rPoint) = 0; + + virtual ~IAbstractTableControl() {}; + }; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_ABSTRACTTABLECONTROL_HXX diff --git a/svtools/inc/svtools/table/defaultinputhandler.hxx b/svtools/inc/svtools/table/defaultinputhandler.hxx new file mode 100644 index 000000000000..eb1c14b43a85 --- /dev/null +++ b/svtools/inc/svtools/table/defaultinputhandler.hxx @@ -0,0 +1,67 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_DEFAULTINPUTHANDLER_HXX +#define SVTOOLS_INC_TABLE_DEFAULTINPUTHANDLER_HXX + +#include <svtools/table/tableinputhandler.hxx> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + struct DefaultInputHandler_Impl; + + //==================================================================== + //= DefaultInputHandler + //==================================================================== + class DefaultInputHandler : public ITableInputHandler + { + friend class TableDataWindow; + private: + DefaultInputHandler_Impl* m_pImpl; + + public: + DefaultInputHandler(); + ~DefaultInputHandler(); + + virtual bool MouseMove ( IAbstractTableControl& _rControl, const MouseEvent& rMEvt ); + virtual bool MouseButtonDown ( IAbstractTableControl& _rControl, const MouseEvent& rMEvt ); + virtual bool MouseButtonUp ( IAbstractTableControl& _rControl, const MouseEvent& rMEvt ); + virtual bool KeyInput ( IAbstractTableControl& _rControl, const KeyEvent& rKEvt ); + virtual bool GetFocus ( IAbstractTableControl& _rControl ); + virtual bool LoseFocus ( IAbstractTableControl& _rControl ); + virtual bool RequestHelp ( IAbstractTableControl& _rControl, const HelpEvent& rHEvt ); + virtual bool Command ( IAbstractTableControl& _rControl, const CommandEvent& rCEvt ); + virtual bool PreNotify ( IAbstractTableControl& _rControl, NotifyEvent& rNEvt ); + virtual bool Notify ( IAbstractTableControl& _rControl, NotifyEvent& rNEvt ); + }; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_DEFAULTINPUTHANDLER_HXX diff --git a/svtools/inc/svtools/table/gridtablerenderer.hxx b/svtools/inc/svtools/table/gridtablerenderer.hxx new file mode 100644 index 000000000000..a935f6b7386e --- /dev/null +++ b/svtools/inc/svtools/table/gridtablerenderer.hxx @@ -0,0 +1,103 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_GRIDTABLERENDERER_HXX +#define SVTOOLS_INC_TABLE_GRIDTABLERENDERER_HXX + +#include <svtools/table/tablemodel.hxx> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + struct GridTableRenderer_Impl; + + //==================================================================== + //= GridTableRenderer + //==================================================================== + /** a default implementation for the ->ITableRenderer interface + + This class is able to paint a table grid, table headers, and cell + backgrounds according to the selected/active state of cells. + + TODO update the documentation when it's decided whether this renderer + also does value handling + */ + class GridTableRenderer : public ITableRenderer + { + private: + GridTableRenderer_Impl* m_pImpl; + + public: + /** creates a table renderer associated with the given model + + @param _rModel + the model which should be rendered. The caller is responsible + for lifetime control, that is, the model instance must live + at least as long as the renderer instance lives + */ + GridTableRenderer( ITableModel& _rModel ); + ~GridTableRenderer(); + + /** returns the index of the row currently being painted + + According to the ->ITableRenderer interface, one call is made + to the renderer with a row to prepare (->PrepareRow()), and subsequent + calls do not carry the row index anymore, but are relative to the + row which has previously been prepared. + + This method returns the index of the last row which has been prepared + */ + RowPos getCurrentRow(); + + protected: + // ITableRenderer overridables + virtual void PaintHeaderArea( + OutputDevice& _rDevice, const Rectangle& _rArea, + bool _bIsColHeaderArea, bool _bIsRowHeaderArea, + const StyleSettings& _rStyle ); + virtual void PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle ); + virtual void PrepareRow( RowPos _nRow, bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rRowArea, + const StyleSettings& _rStyle ); + virtual void PaintRowHeader( + bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle, rtl::OUString& _rText ); + virtual void PaintCell( ColPos _nColumn, + bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle, rtl::OUString& _rText ); + virtual void ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect); + virtual void HideCellCursor( Window& _rView, const Rectangle& _rCursorRect); + }; +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_GRIDTABLERENDERER_HXX diff --git a/svtools/inc/svtools/table/tablecontrol.hxx b/svtools/inc/svtools/table/tablecontrol.hxx new file mode 100644 index 000000000000..98fddcb7d9e1 --- /dev/null +++ b/svtools/inc/svtools/table/tablecontrol.hxx @@ -0,0 +1,174 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_TABLECONTROL_HXX +#define SVTOOLS_INC_TABLE_TABLECONTROL_HXX + +#include <svtools/table/tablemodel.hxx> +#include <vcl/ctrl.hxx> +#include <vcl/seleng.hxx> +#include <svtools/table/tabledatawindow.hxx> +//........................................................................ + +namespace svt { namespace table +{ +//........................................................................ + + class TableControl_Impl; + class TableDataWindow; + //==================================================================== + //= TableControl + //==================================================================== + /** a basic control which manages table-like data, i.e. a number of cells + organized in <code>m</code> rows and <code>n</code> columns. + + The control itself does not do any assumptions about the concrete data + it displays, this is encapsulated in an instance supporting the + ->ITableModel interface. + + Also, the control does not do any assumptions about how the model's + content is rendered. This is the responsibility of a component + supporting the ->ITableRenderer interface (the renderer is obtained from + the model). + + The control supports the concept of a <em>current</em> (or <em>active</em> + cell). + + // TODO: scrolling? + */ + class TableControl : public Control + { + private: + DECL_LINK( ImplMouseButtonDownHdl, MouseEvent* ); + DECL_LINK( ImplMouseButtonUpHdl, MouseEvent* ); + + TableControl_Impl* m_pImpl; + public: + TableControl( Window* _pParent, WinBits _nStyle ); + ~TableControl(); + + /// sets a new table model + void SetModel( PTableModel _pModel ); + /// retrieves the current table model + PTableModel GetModel() const; + + /// returns the top row, i.e. the first visible row + RowPos GetTopRow() const; + /// sets a new top row. The top row is the first visible row in the control + void SetTopRow( RowPos _nRow ); + + /** retrieves the current row + + The current row is the one which contains the active cell. + + @return + the row index of the active cell, or ->ROW_INVALID + if there is no active cell, e.g. because the table does + not contain any rows or columns. + */ + RowPos GetCurrentRow() const; + + /** returns the row, which contains the input point*/ + + RowPos GetCurrentRow (const Point& rPoint); + + /** retrieves the current column + + The current col is the one which contains the active cell. + + @return + the column index of the active cell, or ->COL_INVALID + if there is no active cell, e.g. because the table does + not contain any rows or columns. + */ + ColPos GetCurrentColumn() const; + + /** activates the cell at the given position + + @return + <TRUE/> if the move was successful, <FALSE/> otherwise. Usual + failure conditions include some other instance vetoing the move, + or impossibility to execute the move at all (for instance because + of invalid coordinates). + */ + bool GoTo( ColPos _nColumn, RowPos _nRow ); + + /** moves the active cell to the given column, by keeping the active row + + @return + <TRUE/> if the move was successful, <FALSE/> otherwise. Usual + failure conditions include some other instance vetoing the move, + or impossibility to execute the move at all (for instance because + of invalid coordinates). + */ + inline bool GoToColumn( ColPos _nColumn ) + { + return GoTo( _nColumn, GetCurrentRow() ); + } + + /** moves the active cell to the given row, by keeping the active column + + @return + <TRUE/> if the move was successful, <FALSE/> otherwise. Usual + failure conditions include some other instance vetoing the move, + or impossibility to execute the move at all (for instance because + of invalid coordinates). + */ + bool GoToRow( RowPos _nRow ) + { + return GoTo( GetCurrentColumn(), _nRow ); + } + virtual void Resize(); + + /**invalidates the table if table has been changed e.g. new row added + */ + void InvalidateDataWindow(RowPos _nRowStart, bool _bRemoved); + /**gets the vector, which contains the selected rows + */ + std::vector<RowPos> 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); + + private: + TableControl(); // never implemented + TableControl( const TableControl& ); // never implemented + TableControl& operator=( const TableControl& ); // never implemented + }; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_TABLECONTROL_HXX diff --git a/svtools/inc/svtools/table/tabledatawindow.hxx b/svtools/inc/svtools/table/tabledatawindow.hxx new file mode 100644 index 000000000000..fddbfdcd4a3c --- /dev/null +++ b/svtools/inc/svtools/table/tabledatawindow.hxx @@ -0,0 +1,75 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_SOURCE_TABLE_TABLEDATAWINDOW_HXX +#define SVTOOLS_SOURCE_TABLE_TABLEDATAWINDOW_HXX + +#ifndef _SV_WINDOW_HXX +#include <vcl/window.hxx> +#endif +#include <vcl/seleng.hxx> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + class TableControl_Impl; + class TableFunctionSet; + + + //==================================================================== + //= TableDataWindow + //==================================================================== + /** the window containing the content area (including headers) of + a table control + */ + class TableDataWindow : public Window + { + friend class TableFunctionSet; + private: + TableControl_Impl& m_rTableControl; + Link m_aMouseButtonDownHdl; + Link m_aMouseButtonUpHdl; + + public: + TableDataWindow( TableControl_Impl& _rTableControl ); + inline void SetMouseButtonDownHdl( const Link& rLink ) { m_aMouseButtonDownHdl = rLink; } + inline const Link& GetMouseButtonDownHdl() const { return m_aMouseButtonDownHdl; } + inline void SetMouseButtonUpHdl( const Link& rLink ) { m_aMouseButtonUpHdl = rLink; } + inline const Link& GetMouseButtonUpHdl() const { return m_aMouseButtonUpHdl; } + + // Window overridables + virtual void Paint( const Rectangle& rRect ); + virtual void MouseMove( const MouseEvent& rMEvt); + virtual void MouseButtonDown( const MouseEvent& rMEvt); + virtual void MouseButtonUp( const MouseEvent& rMEvt); + + }; +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_SOURCE_TABLE_TABLEDATAWINDOW_HXX diff --git a/svtools/inc/svtools/table/tableinputhandler.hxx b/svtools/inc/svtools/table/tableinputhandler.hxx new file mode 100644 index 000000000000..c0d3a2b5c18a --- /dev/null +++ b/svtools/inc/svtools/table/tableinputhandler.hxx @@ -0,0 +1,77 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_TABLEINPUTHANDLER_HXX +#define SVTOOLS_INC_TABLE_TABLEINPUTHANDLER_HXX + +#include <boost/shared_ptr.hpp> + +class MouseEvent; +class KeyEvent; +class HelpEvent; +class CommandEvent; +class NotifyEvent; + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + class IAbstractTableControl; + + //==================================================================== + //= ITableInputHandler + //==================================================================== + /** interface for components handling input in a ->TableControl + */ + class ITableInputHandler + { + public: + // all those methods have the same semantics as the equal-named methods of ->Window, + // with the additional option to return a boolean value indicating whether + // the event should be further processed by the ->Window implementations (<FALSE/>), + // or whether it has been sufficiently handled by the ->ITableInputHandler instance + // (<FALSE/>). + + virtual bool MouseMove ( IAbstractTableControl& _rControl, const MouseEvent& rMEvt ) = 0; + virtual bool MouseButtonDown ( IAbstractTableControl& _rControl, const MouseEvent& rMEvt ) = 0; + virtual bool MouseButtonUp ( IAbstractTableControl& _rControl, const MouseEvent& rMEvt ) = 0; + virtual bool KeyInput ( IAbstractTableControl& _rControl, const KeyEvent& rKEvt ) = 0; + virtual bool GetFocus ( IAbstractTableControl& _rControl ) = 0; + virtual bool LoseFocus ( IAbstractTableControl& _rControl ) = 0; + virtual bool RequestHelp ( IAbstractTableControl& _rControl, const HelpEvent& rHEvt ) = 0; + virtual bool Command ( IAbstractTableControl& _rControl, const CommandEvent& rCEvt ) = 0; + virtual bool PreNotify ( IAbstractTableControl& _rControl, NotifyEvent& rNEvt ) = 0; + virtual bool Notify ( IAbstractTableControl& _rControl, NotifyEvent& rNEvt ) = 0; + + virtual ~ITableInputHandler() { } + }; + typedef ::boost::shared_ptr< ITableInputHandler > PTableInputHandler; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_TABLEINPUTHANDLER_HXX diff --git a/svtools/inc/svtools/table/tablemodel.hxx b/svtools/inc/svtools/table/tablemodel.hxx new file mode 100644 index 000000000000..a1af1e1750ed --- /dev/null +++ b/svtools/inc/svtools/table/tablemodel.hxx @@ -0,0 +1,454 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_TABLEMODEL_HXX +#define SVTOOLS_INC_TABLE_TABLEMODEL_HXX + +#include <svtools/table/tabletypes.hxx> +#include <svtools/table/tablerenderer.hxx> +#include <svtools/table/tableinputhandler.hxx> + +#include <sal/types.h> + +#include <boost/shared_ptr.hpp> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + + //==================================================================== + //= cell data + //==================================================================== + struct CellEntryType + { + String m_aStr; + //Image m_aImage; + //Control m_aControl; + CellEntryType( const String& _rStr ) : + m_aStr( _rStr ) + {} + }; + + //typedef ::std::vector<CellEntryType*> CellColumnContent; + //vector, which contains text data for each cell + typedef ::std::vector<String> CellColumnContent; + //vector, which contains data for rows + typedef ::std::vector<CellColumnContent> CellContent; + //==================================================================== + //= ScrollbarVisibility + //==================================================================== + enum ScrollbarVisibility + { + /** enumeration value denoting that a scrollbar should never be visible, even + if needed normally + */ + ScrollbarShowNever, + /** enumeration value denoting that a scrollbar should be visible when needed only + */ + ScrollbarShowSmart, + /** enumeration value denoting that a scrollbar should always be visible, even + if not needed normally + */ + ScrollbarShowAlways + }; + + //==================================================================== + //= ITableModelListener + //==================================================================== + /** declares an interface to be implemented by components interested in + changes in an ->ITableModel + */ + class SAL_NO_VTABLE ITableModelListener + { + public: + //virtual void onTableModelChanged(PTableModel pTableModel) = 0; + /** notifies the listener that one or more rows have been inserted into + the table + + @param first + the index of the first newly inserted row + @param last + the index of the last newly inserted row. Must not be smaller + than ->first + */ + virtual void rowsInserted( RowPos first, RowPos last ) = 0; + + /** notifies the listener that one or more rows have been removed from + the table + + @param first + the old index of the first removed row + @param last + the old index of the last removed row. Must not be smaller + than ->first + */ + virtual void rowsRemoved( RowPos first, RowPos last ) = 0; + + /** notifies the listener that one or more columns have been inserted into + the table + + @param first + the index of the first newly inserted row + @param last + the index of the last newly inserted row. Must not be smaller + than ->first + */ + virtual void columnsInserted( ColPos first, ColPos last ) = 0; + + /** notifies the listener that one or more columns have been removed from + the table + + @param first + the old index of the first removed row + @param last + the old index of the last removed row. Must not be smaller + than ->first + */ + virtual void columnsRemoved( ColPos first, ColPos last ) = 0; + + /** notifies the listener that a column in the table has moved + + @param oldIndex + the old index of the column within the model + @param newIndex + the new index of the column within the model + */ + virtual void columnMoved( ColPos oldIndex, ColPos newIndex ) = 0; + + /** notifies the listener that a rectangular cell range in the table + has been updated + + Listeners are required to discard any possibly cached information + they have about the cells in question, in particular any possibly + cached cell values. + */ + virtual void cellsUpdated( ColPos firstCol, ColPos lastCol, RowPos firstRow, RowPos lastRow ) = 0; + + /// deletes the listener instance + virtual ~ITableModelListener(){}; + }; + typedef ::boost::shared_ptr< ITableModelListener > PTableModelListener; + + //==================================================================== + //= IColumnModel + //==================================================================== + /** interface to be implemented by table column models + */ + class SAL_NO_VTABLE IColumnModel + { + public: + /** retrieves the ID of the column + + The semantics of a column id is not defined. It's up to the + implementor of the ->IColumnModel, respectively the ->ITableModel + which provides the column models, to define such a semantics. + + @return + the ID of the column. May be 0 if the table which the column + belongs to does not need and support column ids. + + @see setID + */ + virtual ColumnID getID() const = 0; + + /** sets a new column ID + + @return + <TRUE/> if setting the new ID was successfull. A possible error + conditions is if you try to set an ID which is already used + by another column within the same table. + + @see getID + */ + virtual bool setID( const ColumnID _nID ) = 0; + + /** returns the name of the column + + Column names should be human-readable, but not necessarily unique + within a given table. + + @see setName + */ + virtual String getName() const = 0; + + /** sets a new name for the column + + @see getName + */ + virtual void setName( const String& _rName ) = 0; + + /** determines whether the column can be resized + + @see getMinWidth + @see getMaxWidth + @see getWidth + */ + virtual bool isResizable() const = 0; + + /** declares the column as resizable or fixed in width + + @see getMinWidth + @see getMaxWidth + @see getWidth + */ + virtual void setResizable( bool _bResizable ) = 0; + + /** returns the width of the column, in 1/100 millimeters + + The returned value must be a positive ->TableMetrics value. + + It can also be COLWIDTH_FIT_TO_VIEW, to indicate that the width of the column + should automatically be adjusted to completely fit the view. For instance, a + model's last column could return this value, to indicate that it is to occupy + all horizontal space remaining in the view, after all other columns have been + layouted. + + If there is more than one column with width COLWIDTH_FIT_TO_VIEW in a model, + they're all layouted equal-width. + + If the columns with a read width (i.e. other than COLWIDTH_FIT_TO_VIEW) are, + in sum, wider than the view, then the view is free to choose a real width for any + columns which return COLWIDTH_FIT_TO_VIEW here. + + @see setWidth + @see getMinWidth + @see getMaxWidth + @see COLWIDTH_FIT_TO_VIEW + */ + virtual TableMetrics getWidth() const = 0; + + /** sets a new width for the column + + @param _nWidth + the new width, in 1/100 millimeters + + @see getWidth + */ + virtual void setWidth( TableMetrics _nWidth ) = 0; + + /** returns the minimum width of the column, in 1/100 millimeters, or 0 if the column + does not have a minimal width + + @see setMinWidth + @see getMaxWidth + @see getWidth + */ + virtual TableMetrics getMinWidth() const = 0; + + /** sets the minimum width of the column, in 1/100 millimeters + + @see getMinWidth + @see setMaxWidth + @see setWidth + */ + virtual void setMinWidth( TableMetrics _nMinWidth ) = 0; + + /** returns the maximum width of the column, in 1/100 millimeters, or 0 if the column + does not have a minimal width + + @see setMaxWidth + @see getMinWidth + @see getWidth + */ + virtual TableMetrics getMaxWidth() const = 0; + + /** sets the maximum width of the column, in 1/100 millimeters + + @see getMaxWidth + @see setMinWidth + @see setWidth + */ + virtual void setMaxWidth( TableMetrics _nMaxWidth ) = 0; + + + /// deletes the column model instance + virtual ~IColumnModel() { } + }; + typedef ::boost::shared_ptr< IColumnModel > PColumnModel; + + //==================================================================== + //= ITableModel + //==================================================================== + /** declares the interface to implement by an abtract table model + */ + class SAL_NO_VTABLE ITableModel + { + public: + /** returns the number of columns in the table + */ + virtual TableSize getColumnCount() const = 0; + + /** returns the number of rows in the table + */ + virtual TableSize getRowCount() const = 0; + + virtual void setColumnCount(TableSize _nColCount) = 0; + virtual void setRowCount(TableSize _nRowCount) = 0; + + /** determines whether the table has column headers + + If this method returns <TRUE/>, the renderer returned by + ->getRenderer must be able to render column headers. + + @see IColumnRenderer + */ + virtual bool hasColumnHeaders() const = 0; + /** sets whether the table should have row headers + @see IColumnRenderer + */ + virtual void setRowHeaders( bool rowHeaders) = 0; + + /** sets whether the table should have column headers + @see IColumnRenderer + */ + virtual void setColumnHeaders( bool columnHeaders) = 0; + + /** determines whether the table has row headers + + If this method returns <TRUE/>, the renderer returned by + ->getRenderer must be able to render row headers. + + @see IColumnRenderer + */ + virtual bool hasRowHeaders() const = 0; + + /** determines whether the given cell is editable + + @see ICellEditor + @todo + */ + virtual bool isCellEditable( ColPos col, RowPos row ) const = 0; + + /** adds the given listener to the list of ->ITableModelListener's + */ + virtual void addTableModelListener( const PTableModelListener& listener ) = 0; + + /** revokes the given listener from the list of ->ITableModelListener's + */ + virtual void removeTableModelListener( const PTableModelListener& listener ) = 0; + + /** returns a model for a certain column + + @param column + the index of the column in question. Must be greater than or + equal 0, and smaller than the return value of ->getColumnCount() + + @return + the model of the column in question. Must not be <NULL/> + + @see getColumnModelByID + */ + virtual PColumnModel getColumnModel( ColPos column ) = 0; + + /** finds a column model by ID + + @param id + the id of the column which is to be looked up + @return + the column model with the given ID, or <NULL/> if there is + no such column + */ + virtual PColumnModel getColumnModelByID( ColumnID id ) = 0; + + /** returns a renderer which is able to paint the table represented + by this table model + + @return the renderer to use. Must not be <NULL/> + */ + virtual PTableRenderer getRenderer() const = 0; + + /** returns the component handling input in a view associated with the model + */ + virtual PTableInputHandler getInputHandler() const = 0; + + /** determines the height of rows in the table. + + @return + the logical height of rows in the table, in 1/100 millimeters. The height must be + greater 0. + */ + virtual TableMetrics getRowHeight() const = 0; + + virtual void setRowHeight(TableMetrics _nRowHeight) = 0; + + /** determines the height of the column header row + + This method is not to be called if ->hasColumnHeaders() + returned <FALSE/>. + + @return + the logical height of the column header row, in 1/100 millimeters. + Must be greater than 0. + */ + virtual TableMetrics getColumnHeaderHeight() const = 0; + + /** determines the width of the row header column + + This method is not to be called if ->hasRowHeaders() + returned <FALSE/>. + + @return + the logical width of the row header column, in 1/100 millimeters. + Must be greater than 0. + */ + virtual TableMetrics getRowHeaderWidth() const = 0; + + /** determines the visibility of the vertical scrollbar of the table control + @param overAllHeight the height of the table with all rows + @param actHeight the given height of the table + */ + virtual ScrollbarVisibility getVerticalScrollbarVisibility(int overAllHeight,int actHeight) const = 0; + + /** determines the visibility of the horizontal scrollbar of the table control + @param overAllWidth the width of the table with all columns + @param actWidth the given width of the table + */ + virtual ScrollbarVisibility getHorizontalScrollbarVisibility(int overAllWidth, int actWidth) const = 0; + + /** fills cells with content + */ + 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; + /**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; + + /// destroys the table model instance + virtual ~ITableModel() { } + }; + typedef ::boost::shared_ptr< ITableModel > PTableModel; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_TABLEMODEL_HXX diff --git a/svtools/inc/svtools/table/tablerenderer.hxx b/svtools/inc/svtools/table/tablerenderer.hxx new file mode 100644 index 000000000000..eb645ad574c4 --- /dev/null +++ b/svtools/inc/svtools/table/tablerenderer.hxx @@ -0,0 +1,241 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_TABLERENDERER_HXX +#define SVTOOLS_INC_TABLE_TABLERENDERER_HXX + +#include <svtools/table/tabletypes.hxx> + +#include <vcl/outdev.hxx> + +#include <boost/shared_ptr.hpp> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + //==================================================================== + //= ITableRenderer + //==================================================================== + /** interface to implement by components rendering a ->TableControl + */ + class SAL_NO_VTABLE ITableRenderer + { + public: + /** paints a (part of) header area + + There are two header areas in a table control: + <ul><li>The row containing all column headers, i.e. <em>above</em> all rows containing the data</li> + <li>The column containing all row headers. i.e. <em>left of</em> all columns containing the data</li> + </ul> + + A header area is more than the union of the single column/row headers. + + First, there might be less columns than fit into the view - in this case, right + beside the right-most column, there's still room which belongs to the column header + area, but is not occupied by any particular column header.<br/> + An equivalent statement holds for the row header area, if there are less rows than + fit into the view. + + Second, if the table control has both a row header and a column header, + the intersection between those both belongs to both the column header area and the + row header area, but not to any particular column or row header. + + There are two flags specifying whether the to-be-painted area is part of the column + and/or row header area. + <ul><li>If both are <TRUE/>, the intersection of both areas is to be painted.</li> + <li>If ->_bIsColHeaderArea is <TRUE/> and ->_bIsRowHeaderArea is <FALSE/>, + then ->_rArea denotes the column header area <em>excluding</em> the + intersection between row and column header area.</li> + <li>Equivalently for ->_bIsColHeaderArea being <FALSE/> and ->_bIsRowHeaderArea + being <TRUE/></li> + </ul> + Note that it's not possible for both ->_bIsColHeaderArea and ->_bIsRowHeaderArea + to be <FALSE/> at the same time. + + @param _rDevice + the device to paint onto + @param _rArea + the area to paint into + @param _bIsColHeaderArea + <TRUE/> if and only if ->_rArea is part of the column header area. + @param _bIsRowHeaderArea + <TRUE/> if and only if ->_rArea is part of the row header area. + @param _rStyle + the style to be used for drawing + */ + virtual void PaintHeaderArea( + OutputDevice& _rDevice, const Rectangle& _rArea, + bool _bIsColHeaderArea, bool _bIsRowHeaderArea, + const StyleSettings& _rStyle ) = 0; + + /** paints the header for a given column + + @param _nCol + the index of the column to paint + @param _bActive + <TRUE/> if and only if the column whose column is to be painted + contains the active cell. + @param _bSelected + <TRUE/> if and only if the column whose column is to be painted + is selected currently. + @param _rDevice + denotes the device to paint onto + @param _rArea + the are into which the column header should be painted + @param _rStyle + the style to be used for drawing + */ + virtual void PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle ) = 0; + + /** prepares a row for painting + + Painting a table means painting rows as necessary, in an increasing + order. The assumption is that retrieving data for two different rows + is (potentially) more expensive than retrieving data for two different + columns. Thus, the renderer will get the chance to "seek" to a certain + row, and then has to render all cells in this row, before another + row is going to be painted. + + @param _nRow + the row which is going to be painted. The renderer should + at least remember this row, since subsequent calls to + ->PaintRowHeader(), ->PaintCell(), and ->FinishRow() will + not pass this parameter again. + + However, the renderer is also allowed to render any + cell-independent content of this row. + + @param _bActive + <TRUE/> if and only if the row to be painted contains the + currently active cell. + @param _bSelected + <TRUE/> if and only if the row to be prepared is + selected currently. + @param _rDevice + denotes the device to paint onto + @param _rRowArea + the are into which the row should be painted. This excludes + the row header area, if applicable. + @param _rStyle + the style to be used for drawing + */ + virtual void PrepareRow( RowPos _nRow, bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rRowArea, + const StyleSettings& _rStyle ) = 0; + + /** paints the header of a row + + The row to be painted is denoted by the most recent call to + ->PrepareRow. + + @param _bActive + <TRUE/> if and only if the row to be painted contains the + currently active cell. + <br/> + Note that this flag is equal to the respective flag in the + previous ->PrepareRow call, it's passed here for convinience + only. + @param _bSelected + <TRUE/> if and only if the row whose header cell is to be + painted is selected currently. + <br/> + Note that this flag is equal to the respective flag in the + previous ->PrepareRow call, it's passed here for convinience + only. + @param _rDevice + denotes the device to paint onto + @param _rArea + the are into which the row header should be painted + @param _rStyle + the style to be used for drawing + @param _rText + the title of the header row + */ + virtual void PaintRowHeader( + bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle, rtl::OUString& _rText ) = 0; + + /** paints a certain cell + + The row to be painted is denoted by the most recent call to + ->PrepareRow. + + @param _bSelected + <TRUE/> if and only if the cell to be painted is + selected currently. This is the case if either + the row or the column of the cell is currently selected. + <br/> + Note that this flag is equal to the respective flag in the + previous ->PrepareRow call, it's passed here for convinience + only. + @param _bActive + <TRUE/> if the cell is currently active. + <br/> + Note that this flag is equal to the respective flag in the + previous ->PrepareRow call, it's passed here for convinience + only. + @param _rDevice + denotes the device to paint onto + @param _rArea + the are into which the cell should be painted + @param _rStyle + the style to be used for drawing + @param _rText + the content of the cell + */ + virtual void PaintCell( ColPos _nColumn, + bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle, rtl::OUString& _rText ) = 0; + + /** draws a cell cursor in the given rectangle + + The cell cursor is used to indicate the active/current cell + of a table control. + */ + virtual void ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect) = 0; + + /** hides the cell cursor previously drawn into the given rectangle + + The cell cursor is used to indicate the active/current cell + of a table control. + */ + virtual void HideCellCursor( Window& _rView, const Rectangle& _rCursorRect) = 0; + + /// deletes the renderer instance + virtual ~ITableRenderer() { } + }; + typedef ::boost::shared_ptr< ITableRenderer > PTableRenderer; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_TABLERENDERER_HXX diff --git a/svtools/inc/svtools/table/tabletypes.hxx b/svtools/inc/svtools/table/tabletypes.hxx new file mode 100644 index 000000000000..167e49cfd521 --- /dev/null +++ b/svtools/inc/svtools/table/tabletypes.hxx @@ -0,0 +1,75 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_INC_TABLE_TABLETYPES_HXX +#define SVTOOLS_INC_TABLE_TABLETYPES_HXX + +#include <sal/types.h> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + /// a value denoting the size of a table + typedef sal_Int32 TableSize; + + /// a value denoting a column position within a table + typedef sal_Int32 ColPos; + /// a value denoting a row position within a table + typedef sal_Int32 RowPos; + + /** a value denoting an arbitrary coordinate value of a position within + a table + + Values of this type are guaranteed to be large enough to hold column + positions as well as row positions. + */ + typedef sal_Int32 AnyPos; + + /// the ID of a column in a table + typedef sal_Int32 ColumnID; + + typedef sal_Int32 TableMetrics; +/** special column width value which indicates that the column should be + automatically resized to fit the view +*/ +#define COLWIDTH_FIT_TO_VIEW ((TableMetrics)-1) + +/// denotes the column containing the row headers +#define COL_ROW_HEADERS ((ColPos)-1) +/// denotes the row containing the column headers +#define ROW_COL_HEADERS ((RowPos)-1) + +/// denotes an invalid column index +#define COL_INVALID ((ColPos)-2) +/// denotes an invalid row index +#define ROW_INVALID ((RowPos)-2) + + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_INC_TABLE_TABLETYPES_HXX diff --git a/svtools/prj/build.lst b/svtools/prj/build.lst index a6a409055faa..a60199740561 100644 --- a/svtools/prj/build.lst +++ b/svtools/prj/build.lst @@ -38,13 +38,14 @@ st svtools\source\undo nmake - all st_undo st_inc NULL st svtools\source\plugapp nmake - all st_papp st_inc NULL st svtools\source\dialogs nmake - all st_dial st_inc NULL st svtools\source\edit nmake - all st_edit st_inc NULL +st svtools\source\table nmake - all st_table st_inc NULL st svtools\source\uno nmake - all st_uno st_inc NULL st svtools\source\svrtf nmake - all st_rtf st_inc NULL st svtools\source\svsql nmake - all st_sql st_inc NULL st svtools\source\svhtml nmake - all st_html st_inc NULL st svtools\source\syslocale nmake - all st_sysloc st_inc NULL st svtools\source\filepicker nmake - all st_filepick st_inc NULL -st svtools\util nmake - all st_util st__brw st__ctr st__dde st__item st__item1 st__misc st__misc1 st__url st_ctl st_dial st_edit st_file st_html st_papp st_rtf st_sql st_usdde.u st_psdde.p st_msdde.m st_msc.m st_undo st_uno st_vfilt st_vigif st_vixbm st_vixpm st_vjpeg st_vwmf st_sysloc st_filepick st_not st_conf st_mem st_num st_svtjava NULL +st svtools\util nmake - all st_util st__brw st__ctr st__dde st__item st__item1 st__misc st__misc1 st__url st_ctl st_dial st_edit st_file st_html st_papp st_rtf st_sql st_usdde.u st_psdde.p st_msdde.m st_msc.m st_undo st_table st_uno st_vfilt st_vigif st_vixbm st_vixpm st_vjpeg st_vwmf st_sysloc st_filepick st_not st_conf st_mem st_num st_svtjava NULL st svtools\source\fsstor nmake - all st_fsstor st_inc NULL st svtools\source\hatchwindow nmake - all st_hatchwin st_inc NULL st svtools\source\passwordcontainer nmake - all st_passcont st_inc NULL diff --git a/svtools/source/items1/itemset.cxx b/svtools/source/items1/itemset.cxx index 6edeffe6d250..fee00dca854a 100644 --- a/svtools/source/items1/itemset.cxx +++ b/svtools/source/items1/itemset.cxx @@ -541,7 +541,7 @@ SfxItemState SfxItemSet::GetItemState( USHORT nWhich, // Unterschiedlich vorhanden return SFX_ITEM_DONTCARE; - if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) )
+ if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) ) return SFX_ITEM_DISABLED; if (ppItem) diff --git a/svtools/source/table/defaultinputhandler.cxx b/svtools/source/table/defaultinputhandler.cxx new file mode 100644 index 000000000000..17ee0222857f --- /dev/null +++ b/svtools/source/table/defaultinputhandler.cxx @@ -0,0 +1,210 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "svtools/table/defaultinputhandler.hxx" +#include "svtools/table/abstracttablecontrol.hxx" + +#include <tools/debug.hxx> +#include <vcl/event.hxx> +#include <vcl/cursor.hxx> +#include "svtools/table/tabledatawindow.hxx" + +//........................................................................ +namespace svt { namespace table +{ +//....................................................................... + + struct DefaultInputHandler_Impl + { + }; + + //==================================================================== + //= DefaultInputHandler + //==================================================================== + //-------------------------------------------------------------------- + DefaultInputHandler::DefaultInputHandler() + :m_pImpl( new DefaultInputHandler_Impl ) + { + } + + //-------------------------------------------------------------------- + DefaultInputHandler::~DefaultInputHandler() + { + DELETEZ( m_pImpl ); + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::MouseMove( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt ) + { + (void)_rControl; + (void)_rMEvt; + return false; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::MouseButtonDown( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt ) + { + bool bHandled = false; + Point aPoint = _rMEvt.GetPosPixel(); + if(_rControl.isClickInVisibleArea(aPoint)) + { + if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION) + { + LoseFocus(_rControl); + _rControl.setCursorAtCurrentCell(aPoint); + bHandled = true; + } + else + { + bHandled = _rControl.getSelEngine()->SelMouseButtonDown(_rMEvt); + } + } + return bHandled; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::MouseButtonUp( IAbstractTableControl& _rControl, const MouseEvent& _rMEvt ) + { + bool bHandled = false; + Point aPoint = _rMEvt.GetPosPixel(); + if(_rControl.isClickInVisibleArea(aPoint)) + { + if(_rControl.getSelEngine()->GetSelectionMode() == NO_SELECTION) + { + GetFocus(_rControl); + _rControl.setCursorAtCurrentCell(aPoint); + bHandled = true; + } + else + bHandled = _rControl.getSelEngine()->SelMouseButtonUp(_rMEvt); + } + return bHandled; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::KeyInput( IAbstractTableControl& _rControl, const KeyEvent& rKEvt ) + { + bool bHandled = false; + + const KeyCode& rKeyCode = rKEvt.GetKeyCode(); + USHORT nKeyCode = rKeyCode.GetCode(); + + struct _ActionMapEntry + { + USHORT nKeyCode; + USHORT nKeyModifier; + TableControlAction eAction; + } + static aKnownActions[] = { + { KEY_DOWN, 0, cursorDown }, + { KEY_UP, 0, cursorUp }, + { KEY_LEFT, 0, cursorLeft }, + { KEY_RIGHT, 0, cursorRight }, + { KEY_HOME, 0, cursorToLineStart }, + { KEY_END, 0, cursorToLineEnd }, + { KEY_PAGEUP, 0, cursorPageUp }, + { KEY_PAGEDOWN, 0, cursorPageDown }, + { KEY_PAGEUP, KEY_MOD1, cursorToFirstLine }, + { KEY_PAGEDOWN, KEY_MOD1, cursorToLastLine }, + { KEY_HOME, KEY_MOD1, cursorTopLeft }, + { KEY_END, KEY_MOD1, cursorBottomRight }, + { KEY_SPACE, KEY_MOD1, cursorSelectRow }, + { KEY_UP, KEY_SHIFT, cursorSelectRowUp }, + { KEY_DOWN, KEY_SHIFT, cursorSelectRowDown }, + { KEY_END, KEY_SHIFT, cursorSelectRowAreaBottom }, + { KEY_HOME, KEY_SHIFT, cursorSelectRowAreaTop }, + + { 0, 0, invalidTableControlAction } + }; + + const _ActionMapEntry* pActions = aKnownActions; + for ( ; pActions->eAction != invalidTableControlAction; ++pActions ) + { + if ( ( pActions->nKeyCode == nKeyCode ) && ( pActions->nKeyModifier == rKeyCode.GetAllModifier() ) ) + { + bHandled = _rControl.dispatchAction( pActions->eAction ); + break; + } + } + + return bHandled; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::GetFocus( IAbstractTableControl& _rControl ) + { + _rControl.showCursor(); + return false; // continue processing + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::LoseFocus( IAbstractTableControl& _rControl ) + { + _rControl.hideCursor(); + return false; // continue processing + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::RequestHelp( IAbstractTableControl& _rControl, const HelpEvent& _rHEvt ) + { + (void)_rControl; + (void)_rHEvt; + // TODO + return false; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::Command( IAbstractTableControl& _rControl, const CommandEvent& _rCEvt ) + { + (void)_rControl; + (void)_rCEvt; + // TODO + return false; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::PreNotify( IAbstractTableControl& _rControl, NotifyEvent& _rNEvt ) + { + (void)_rControl; + (void)_rNEvt; + // TODO + return false; + } + + //-------------------------------------------------------------------- + bool DefaultInputHandler::Notify( IAbstractTableControl& _rControl, NotifyEvent& _rNEvt ) + { + (void)_rControl; + (void)_rNEvt; + // TODO + return false; + } + +//........................................................................ +} } // namespace svt::table +//........................................................................ diff --git a/svtools/source/table/gridtablerenderer.cxx b/svtools/source/table/gridtablerenderer.cxx new file mode 100644 index 000000000000..2c4fda711009 --- /dev/null +++ b/svtools/source/table/gridtablerenderer.cxx @@ -0,0 +1,234 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "svtools/table/gridtablerenderer.hxx" + +#include <tools/debug.hxx> +#include <vcl/window.hxx> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + struct GridTableRenderer_Impl + { + ITableModel& rModel; + RowPos nCurrentRow; + + GridTableRenderer_Impl( ITableModel& _rModel ) + :rModel( _rModel ) + ,nCurrentRow( ROW_INVALID ) + { + } + }; + + //==================================================================== + //= GridTableRenderer + //==================================================================== + //-------------------------------------------------------------------- + GridTableRenderer::GridTableRenderer( ITableModel& _rModel ) + :m_pImpl( new GridTableRenderer_Impl( _rModel ) ) + { + } + + //-------------------------------------------------------------------- + GridTableRenderer::~GridTableRenderer() + { + DELETEZ( m_pImpl ); + } + + //-------------------------------------------------------------------- + RowPos GridTableRenderer::getCurrentRow() + { + return m_pImpl->nCurrentRow; + } + + //-------------------------------------------------------------------- + void GridTableRenderer::PaintHeaderArea( + OutputDevice& _rDevice, const Rectangle& _rArea, bool _bIsColHeaderArea, bool _bIsRowHeaderArea, + const StyleSettings& _rStyle ) + { + OSL_PRECOND( _bIsColHeaderArea || _bIsRowHeaderArea, + "GridTableRenderer::PaintHeaderArea: invalid area flags!" ); + + // fill the rows with alternating background colors + _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); + + _rDevice.SetLineColor(); + _rDevice.SetFillColor( _rStyle.GetDialogColor() ); + _rDevice.DrawRect( _rArea ); + + // delimiter lines at bottom/right + _rDevice.SetLineColor( _rStyle.GetDialogTextColor() ); + _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + + _rDevice.Pop(); + (void)_bIsColHeaderArea; + (void)_bIsRowHeaderArea; + } + + //-------------------------------------------------------------------- + void GridTableRenderer::PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle ) + { + _rDevice.Push( PUSH_LINECOLOR ); + + _rDevice.SetLineColor( _rStyle.GetDialogTextColor() ); + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + + String sHeaderText; + + PColumnModel pColumn = m_pImpl->rModel.getColumnModel( _nCol ); + DBG_ASSERT( !!pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" ); + if ( !!pColumn ) + sHeaderText = pColumn->getName(); + Color aRowBackground = _rStyle.GetFieldColor(); + if ( _bSelected ) + { + aRowBackground = COL_BLUE; + } + _rDevice.DrawText( _rArea, sHeaderText, TEXT_DRAW_LEFT | TEXT_DRAW_TOP ); + _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); + _rDevice.Pop(); + + (void)_bActive; + // no special painting for the active column at the moment + + //(void)_bSelected; + // TODO: selection not yet implemented + } + + //-------------------------------------------------------------------- + void GridTableRenderer::PrepareRow( RowPos _nRow, bool _bActive, bool _bSelected, + OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle ) + { + // remember the row for subsequent calls to the other ->ITableRenderer methods + m_pImpl->nCurrentRow = _nRow; + + // fill the rows with alternating background colors + _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); + + _rDevice.SetLineColor(); + + Color aRowBackground = _rStyle.GetFieldColor(); + + _rDevice.SetFillColor( aRowBackground ); + + _rDevice.DrawRect( _rRowArea ); + + // TODO: active? selected? + + _rDevice.Pop(); + (void) _bSelected; + (void)_bActive; + + // no special painting for the active row at the moment + + //(void)_bSelected; + // TODO: selection not yet implemented + } + + //-------------------------------------------------------------------- + void GridTableRenderer::PaintRowHeader( bool _bActive, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea, + const StyleSettings& _rStyle, rtl::OUString& _rText ) + { + _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); + + _rDevice.SetLineColor( _rStyle.GetDialogTextColor() ); + _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); + _rDevice.DrawText( _rArea, _rText, TEXT_DRAW_LEFT); + // TODO: active? selected? + (void)_bActive; + (void)_bSelected; + + _rDevice.Pop(); + } + + //-------------------------------------------------------------------- + void GridTableRenderer::PaintCell( ColPos _nColumn, bool _bSelected, bool _bActive, + OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle, rtl::OUString& _rText ) + { + _rDevice.Push( PUSH_LINECOLOR ); + + // draw the grid + _rDevice.SetLineColor( COL_LIGHTGRAY ); + // TODO: the LIGHTGRAY should probably be a property/setting + _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() ); + _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() ); + + { + // TODO: remove those temporary place holders + Rectangle aRect( _rArea ); + ++aRect.Left(); --aRect.Right(); + ++aRect.Top(); --aRect.Bottom(); + + String sText; + if(_bSelected) + { + Color aRed(COL_BLUE); + _rDevice.SetFillColor( aRed ); + _rDevice.SetTextColor(COL_WHITE); + } + _rDevice.DrawRect( _rArea ); + (void)_nColumn; + _rDevice.DrawText( aRect, _rText, TEXT_DRAW_LEFT | TEXT_DRAW_TOP); + } + if(_bSelected) + { + _rDevice.SetFillColor( _rStyle.GetFieldColor() ); + _rDevice.SetTextColor(COL_BLACK); + } + + _rDevice.Pop(); + + (void)_bActive; +// // no special painting for the active cell at the moment + (void)_rStyle; +// // TODO: do we need this? + } + + //-------------------------------------------------------------------- + void GridTableRenderer::ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect) + { + _rView.ShowFocus( _rCursorRect ); + } + + //-------------------------------------------------------------------- + void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect) + { + (void)_rCursorRect; + _rView.HideFocus(); + + } + +//........................................................................ +} } // namespace svt::table +//........................................................................ + diff --git a/svtools/source/table/makefile.mk b/svtools/source/table/makefile.mk new file mode 100644 index 000000000000..8feb7fee10d8 --- /dev/null +++ b/svtools/source/table/makefile.mk @@ -0,0 +1,59 @@ +#************************************************************************* +# +# 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: makefile.mk,v $ +# +# $Revision: 1.16 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/.. + +ENABLE_EXCEPTIONS=TRUE +PRJNAME=svtools +TARGET=table +#LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/svt.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES=\ + $(SLO)$/tablecontrol.obj \ + $(SLO)$/tablecontrol_impl.obj \ + $(SLO)$/gridtablerenderer.obj \ + $(SLO)$/tablegeometry.obj \ + $(SLO)$/defaultinputhandler.obj \ + $(SLO)$/tabledatawindow.obj + +#LIB1TARGET= $(SLB)$/$(TARGET).lib +#LIB1OBJFILES= $(SLOFILES) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/svtools/source/table/tablecontrol.cxx b/svtools/source/table/tablecontrol.cxx new file mode 100644 index 000000000000..c8895a19408d --- /dev/null +++ b/svtools/source/table/tablecontrol.cxx @@ -0,0 +1,179 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "svtools/table/tablecontrol.hxx" +#include "tablegeometry.hxx" +#include "tablecontrol_impl.hxx" +#include "svtools/table/tabledatawindow.hxx" +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + //==================================================================== + //= TableControl + //==================================================================== + //-------------------------------------------------------------------- + TableControl::TableControl( Window* _pParent, WinBits _nStyle ) + :Control( _pParent, _nStyle ) + ,m_pImpl( new TableControl_Impl( *this ) ) + { + m_pImpl->getDataWindow()->SetMouseButtonDownHdl( LINK( this, TableControl, ImplMouseButtonDownHdl ) ); + m_pImpl->getDataWindow()->SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) ); + } + + //-------------------------------------------------------------------- + TableControl::~TableControl() + { + DELETEZ( m_pImpl ); + } + + //-------------------------------------------------------------------- + void TableControl::GetFocus() + { + if ( !m_pImpl->getInputHandler()->GetFocus( *m_pImpl ) ) + { + Control::GetFocus(); + GrabFocus(); + } + } + + //-------------------------------------------------------------------- + void TableControl::LoseFocus() + { + if ( !m_pImpl->getInputHandler()->LoseFocus( *m_pImpl ) ) + Control::LoseFocus(); + } + + //-------------------------------------------------------------------- + void TableControl::KeyInput( const KeyEvent& rKEvt ) + { + if ( !m_pImpl->getInputHandler()->KeyInput( *m_pImpl, rKEvt ) ) + Control::KeyInput( rKEvt ); + } + //-------------------------------------------------------------------- + void TableControl::Resize() + { + Control::Resize(); + m_pImpl->onResize(); + } + + //-------------------------------------------------------------------- + void TableControl::SetModel( PTableModel _pModel ) + { + m_pImpl->setModel( _pModel ); + } + + //-------------------------------------------------------------------- + PTableModel TableControl::GetModel() const + { + return m_pImpl->getModel(); + } + + //-------------------------------------------------------------------- + RowPos TableControl::GetTopRow() const + { + return m_pImpl->getTopRow(); + } + + //-------------------------------------------------------------------- + void TableControl::SetTopRow( RowPos _nRow ) + { + // TODO + (void)_nRow; + } + + //-------------------------------------------------------------------- + RowPos TableControl::GetCurrentRow() const + { + return m_pImpl->getCurRow(); + } + + //-------------------------------------------------------------------- + ColPos TableControl::GetCurrentColumn() const + { + return m_pImpl->getCurColumn(); + } + + //-------------------------------------------------------------------- + bool TableControl::GoTo( ColPos _nColumn, RowPos _nRow ) + { + return m_pImpl->goTo( _nColumn, _nRow ); + } + //-------------------------------------------------------------------- + void TableControl::InvalidateDataWindow(RowPos _nRowStart, bool _bRemoved) + { + Rectangle _rRect; + if(_bRemoved) + return m_pImpl->invalidateRows(_nRowStart, _rRect); + else + return m_pImpl->invalidateRow(_nRowStart, _rRect); + } + //-------------------------------------------------------------------- + std::vector<RowPos> TableControl::getSelectedRows() + { + return m_pImpl->getSelectedRows(); + } + //-------------------------------------------------------------------- + void TableControl::removeSelectedRow(RowPos _nRowPos) + { + m_pImpl->removeSelectedRow(_nRowPos); + } + //-------------------------------------------------------------------- + + RowPos TableControl::GetCurrentRow(const Point& rPoint) + { + return m_pImpl->getCurrentRow( rPoint ); + } + + //-------------------------------------------------------------------- + + IMPL_LINK( TableControl, ImplMouseButtonDownHdl, MouseEvent*, pData ) + { + CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, pData ); + return 1; + } + + IMPL_LINK( TableControl, ImplMouseButtonUpHdl, MouseEvent*, pData ) + { + CallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, pData ); + return 1; + } + + SelectionEngine* TableControl::getSelEngine() + { + return m_pImpl->getSelEngine(); + } + + TableDataWindow* TableControl::getDataWindow() + { + return m_pImpl->getDataWindow(); + } +//........................................................................ +} } // namespace svt::table +//........................................................................ diff --git a/svtools/source/table/tablecontrol_impl.cxx b/svtools/source/table/tablecontrol_impl.cxx new file mode 100644 index 000000000000..e1ff3aeb7f2a --- /dev/null +++ b/svtools/source/table/tablecontrol_impl.cxx @@ -0,0 +1,2003 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "svtools/table/tablecontrol.hxx" +#include "svtools/table/defaultinputhandler.hxx" +#include "svtools/table/tablemodel.hxx" +#include "tablecontrol_impl.hxx" +#include "tablegeometry.hxx" +#include "svtools/table/tabledatawindow.hxx" + +#include <vcl/scrbar.hxx> +#include <vcl/seleng.hxx> + +#include <functional> +#include <stdlib.h> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + //==================================================================== + //= TempHideCursor + //==================================================================== + class TempHideCursor + { + private: + IAbstractTableControl& m_rTable; + + public: + TempHideCursor( IAbstractTableControl& _rTable ) + :m_rTable( _rTable ) + { + m_rTable.hideCursor(); + } + ~TempHideCursor() + { + m_rTable.showCursor(); + } + }; + + //==================================================================== + //= EmptyTableModel + //==================================================================== + /** default implementation of an ->ITableModel, used as fallback when no + real model is present + + Instances of this class are static in any way, and provide the least + necessary default functionality for a table model. + */ + class EmptyTableModel : public ITableModel + { + public: + EmptyTableModel() + { + } + + // ITableModel overridables + virtual TableSize getColumnCount() const + { + return 0; + } + virtual TableSize getRowCount() const + { + return 0; + } + virtual bool hasColumnHeaders() const + { + return false; + } + virtual bool hasRowHeaders() const + { + return false; + } + virtual void setRowHeaders(bool _bRowHeaders) + { + (void)_bRowHeaders; + } + virtual void setColumnHeaders(bool _bColumnHeaders) + { + (void)_bColumnHeaders; + } + void setColumnCount(TableSize _nColCount) + { + (void) _nColCount; + } + void setRowCount(TableSize _nRowCount) + { + (void)_nRowCount; + } + virtual bool isCellEditable( ColPos col, RowPos row ) const + { + (void)col; + (void)row; + return false; + } + virtual void addTableModelListener( const PTableModelListener& listener ) + { + (void)listener; + // ignore + } + virtual void removeTableModelListener( const PTableModelListener& listener ) + { + (void)listener; + // ignore + } + virtual PColumnModel getColumnModel( ColPos column ) + { + DBG_ERROR( "EmptyTableModel::getColumnModel: invalid call!" ); + (void)column; + return PColumnModel(); + } + virtual PColumnModel getColumnModelByID( ColumnID id ) + { + DBG_ERROR( "EmptyTableModel::getColumnModel: invalid call!" ); + (void)id; + return PColumnModel(); + } + virtual PTableRenderer getRenderer() const + { + return PTableRenderer(); + } + virtual PTableInputHandler getInputHandler() const + { + return PTableInputHandler(); + } + virtual TableMetrics getRowHeight() const + { + return 5 * 100; + } + virtual void setRowHeight(TableMetrics _nRowHeight) + { + (void)_nRowHeight; + } + virtual TableMetrics getColumnHeaderHeight() const + { + return 0; + } + virtual TableMetrics getRowHeaderWidth() const + { + return 0; + } + virtual ScrollbarVisibility getVerticalScrollbarVisibility(int overAllHeight, int actHeight) const + { + (void)overAllHeight; + (void)actHeight; + return ScrollbarShowNever; + } + virtual ScrollbarVisibility getHorizontalScrollbarVisibility(int overAllWidth, int actWidth) const + { + (void)overAllWidth; + (void)actWidth; + return ScrollbarShowNever; + } + virtual void setCellContent(std::vector<std::vector<rtl::OUString> > pCellEntryType) + { + (void)pCellEntryType; + } + 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; + } + virtual void setRowHeaderName(std::vector<rtl::OUString> pCellEntryType) + { + (void)pCellEntryType; + } + virtual std::vector<rtl::OUString> getRowHeaderName() + { + std::vector<rtl::OUString> cCC; + cCC.push_back(rtl::OUString::createFromAscii("")); + return cCC; + } + }; + + + //==================================================================== + //= TableControl_Impl + //==================================================================== + DBG_NAME( TableControl_Impl ) + +#if DBG_UTIL + //==================================================================== + //= SuspendInvariants + //==================================================================== + class SuspendInvariants + { + private: + const TableControl_Impl& m_rTable; + sal_Int32 m_nSuspendFlags; + + public: + SuspendInvariants( const TableControl_Impl& _rTable, sal_Int32 _nSuspendFlags ) + :m_rTable( _rTable ) + ,m_nSuspendFlags( _nSuspendFlags ) + { + DBG_ASSERT( ( m_rTable.m_nRequiredInvariants & m_nSuspendFlags ) == m_nSuspendFlags, + "SuspendInvariants: cannot suspend what is already suspended!" ); + const_cast< TableControl_Impl& >( m_rTable ).m_nRequiredInvariants &= ~m_nSuspendFlags; + } + ~SuspendInvariants() + { + const_cast< TableControl_Impl& >( m_rTable ).m_nRequiredInvariants |= m_nSuspendFlags; + } + }; + #define DBG_SUSPEND_INV( flags ) \ + SuspendInvariants aSuspendInv( *this, flags ); +#else + #define DBG_SUSPEND_INV( flags ) +#endif + +#if DBG_UTIL + //==================================================================== + const char* TableControl_Impl_checkInvariants( const void* _pInstance ) + { + return static_cast< const TableControl_Impl* >( _pInstance )->impl_checkInvariants(); + } + + namespace + { + template< typename SCALAR_TYPE > + bool lcl_checkLimitsExclusive( SCALAR_TYPE _nValue, SCALAR_TYPE _nMin, SCALAR_TYPE _nMax ) + { + return ( _nValue > _nMin ) && ( _nValue < _nMax ); + } + + template< typename SCALAR_TYPE > + bool lcl_checkLimitsExclusive_OrDefault_OrFallback( SCALAR_TYPE _nValue, SCALAR_TYPE _nMin, SCALAR_TYPE _nMax, + PTableModel _pModel, SCALAR_TYPE _nDefaultOrFallback ) + { + if ( !_pModel ) + return _nValue == _nDefaultOrFallback; + if ( _nMax <= _nMin ) + return _nDefaultOrFallback == _nValue; + return lcl_checkLimitsExclusive( _nValue, _nMin, _nMax ); + } + } + + //-------------------------------------------------------------------- + const sal_Char* TableControl_Impl::impl_checkInvariants() const + { + if ( !m_pModel ) + return "no model, not even an EmptyTableModel"; + + if ( !m_pDataWindow ) + return "invalid data window!"; + + if ( m_pModel->getColumnCount() != m_nColumnCount ) + return "column counts are inconsistent!"; + + if ( m_pModel->getRowCount() != m_nRowCount ) + return "row counts are inconsistent!"; + + if ( ( m_nCurColumn != COL_INVALID ) && !m_aColumnWidthsPixel.empty() && ( m_nCurColumn < 0 ) || ( m_nCurColumn >= (ColPos)m_aColumnWidthsPixel.size() ) ) + return "current column is invalid!"; + + if ( m_aColumnWidthsPixel.size() != m_aAccColumnWidthsPixel.size() ) + return "columnd width caches are inconsistent!"; + + if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nTopRow, (RowPos)-1, m_nRowCount, getModel(), (RowPos)0 ) ) + return "invalid top row value!"; + + if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nCurRow, (RowPos)-1, m_nRowCount, getModel(), ROW_INVALID ) ) + return "invalid current row value!"; + + if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nLeftColumn, (ColPos)-1, m_nColumnCount, getModel(), (ColPos)0 ) ) + return "invalid current column value!"; + + if ( !lcl_checkLimitsExclusive_OrDefault_OrFallback( m_nCurColumn, (ColPos)-1, m_nColumnCount, getModel(), COL_INVALID ) ) + return "invalid current column value!"; + + if ( m_pInputHandler != m_pModel->getInputHandler() ) + return "input handler is not the model-provided one!"; + + // m_nColHeaderHeightPixel consistent with the model's value? + { + TableMetrics nHeaderHeight = m_pModel->hasColumnHeaders() ? m_pModel->getColumnHeaderHeight() : 0; + nHeaderHeight = m_rAntiImpl.LogicToPixel( Size( 0, nHeaderHeight ), MAP_100TH_MM ).Height(); + if ( nHeaderHeight != m_nColHeaderHeightPixel ) + return "column header heights are inconsistent!"; + } + + bool isDummyModel = dynamic_cast< const EmptyTableModel* >( m_pModel.get() ) != NULL; + if ( !isDummyModel ) + { + TableMetrics nRowHeight = m_pModel->getRowHeight(); + nRowHeight = m_rAntiImpl.LogicToPixel( Size( 0, nRowHeight ), MAP_100TH_MM ).Height(); + if ( nRowHeight != m_nRowHeightPixel ) + return "row heights are inconsistent!"; + } + + // m_nRowHeaderWidthPixel consistent with the model's value? + { + TableMetrics nHeaderWidth = m_pModel->hasRowHeaders() ? m_pModel->getRowHeaderWidth() : 0; + nHeaderWidth = m_rAntiImpl.LogicToPixel( Size( nHeaderWidth, 0 ), MAP_100TH_MM ).Width(); + if ( nHeaderWidth != m_nRowHeaderWidthPixel ) + return "row header widths are inconsistent!"; + } + + // TODO: check m_aColumnWidthsPixel and m_aAccColumnWidthsPixel + + if ( m_nCursorHidden < 0 ) + return "invalid hidden count for the cursor!"; + + if ( ( m_nRequiredInvariants & INV_SCROLL_POSITION ) && m_pVScroll ) + { + DBG_SUSPEND_INV( INV_SCROLL_POSITION ); + // prevent infinite recursion + + if ( m_pVScroll->GetThumbPos() != m_nTopRow ) + return "vertical scroll bar |position| is incorrect!"; + if ( m_pVScroll->GetRange().Max() != m_nRowCount ) + return "vertical scroll bar |range| is incorrect!"; + if ( m_pVScroll->GetVisibleSize() != impl_getVisibleRows( false ) ) + return "vertical scroll bar |visible size| is incorrect!"; + } + + if ( ( m_nRequiredInvariants & INV_SCROLL_POSITION ) && m_pHScroll ) + { + DBG_SUSPEND_INV( INV_SCROLL_POSITION ); + // prevent infinite recursion + + if ( m_pHScroll->GetThumbPos() != m_nLeftColumn ) + return "horizontal scroll bar |position| is incorrect!"; + if ( m_pHScroll->GetRange().Max() != m_nColumnCount ) + return "horizontal scroll bar |range| is incorrect!"; + if ( m_pHScroll->GetVisibleSize() != impl_getVisibleColumns( false ) ) + return "horizontal scroll bar |visible size| is incorrect!"; + } + + return NULL; + } +#endif + +#define DBG_CHECK_ME() \ + DBG_CHKTHIS( TableControl_Impl, TableControl_Impl_checkInvariants ) + + //-------------------------------------------------------------------- + TableControl_Impl::TableControl_Impl( TableControl& _rAntiImpl ) + :m_rAntiImpl ( _rAntiImpl ) + ,m_pModel ( new EmptyTableModel ) + ,m_pInputHandler ( ) + ,m_nRowHeightPixel ( 15 ) + ,m_nColHeaderHeightPixel( 0 ) + ,m_nRowHeaderWidthPixel ( 0 ) + ,m_nColumnCount ( 0 ) + ,m_nRowCount ( 0 ) + ,m_nCurColumn ( COL_INVALID ) + ,m_nCurRow ( ROW_INVALID ) + ,m_nLeftColumn ( 0 ) + ,m_nTopRow ( 0 ) + ,m_nCursorHidden ( 1 ) + ,m_pDataWindow ( new TableDataWindow( *this ) ) + ,m_pVScroll ( NULL ) + ,m_pHScroll ( NULL ) + ,m_pScrollCorner ( NULL ) + ,m_pSelEngine ( ) + ,m_nRowSelected ( ) + ,m_pTableFunctionSet ( new TableFunctionSet(this ) ) + ,m_nAnchor (-1 ) +#if DBG_UTIL + ,m_nRequiredInvariants ( INV_SCROLL_POSITION ) +#endif + { + DBG_CTOR( TableControl_Impl, TableControl_Impl_checkInvariants ); + m_pSelEngine = new SelectionEngine(m_pDataWindow, m_pTableFunctionSet); + m_pSelEngine->SetSelectionMode(SINGLE_SELECTION); + m_pDataWindow->SetPosPixel( Point( 0, 0 ) ); + m_pDataWindow->Show(); + } + + //-------------------------------------------------------------------- + TableControl_Impl::~TableControl_Impl() + { + DBG_DTOR( TableControl_Impl, TableControl_Impl_checkInvariants ); + + DELETEZ( m_pVScroll ); + DELETEZ( m_pHScroll ); + DELETEZ( m_pScrollCorner ); + DELETEZ( m_pTableFunctionSet ); + DELETEZ( m_pSelEngine ); + DELETEZ( m_pDataWindow ); + } + + //-------------------------------------------------------------------- + PTableModel TableControl_Impl::getModel() const + { + if ( dynamic_cast< const EmptyTableModel* >( m_pModel.get() ) != NULL ) + // if it's an EmptyTableModel, pretend that there is no model + return PTableModel(); + + return m_pModel; + } + + //-------------------------------------------------------------------- + void TableControl_Impl::setModel( PTableModel _pModel ) + { + DBG_CHECK_ME(); + + TempHideCursor aHideCursor( *this ); + + // TODO: revoke as table listener from the model + + m_pModel = _pModel; + if ( !m_pModel ) + m_pModel.reset( new EmptyTableModel ); + + // TODO: register as table listener + //m_pModel->addTableModelListener(PTableModelListener(m_pTableModelListener)); + m_nCurRow = ROW_INVALID; + m_nCurColumn = COL_INVALID; + + // recalc some model-dependent cached info + impl_ni_updateCachedModelValues(); + + // completely invalidate + m_rAntiImpl.Invalidate(); + + // reset cursor to (0,0) + if ( m_nRowCount ) m_nCurRow = 0; + if ( m_nColumnCount ) m_nCurColumn = 0; + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_getAllVisibleCellsArea( Rectangle& _rCellArea ) const + { + DBG_CHECK_ME(); + + _rCellArea.Left() = 0; + _rCellArea.Top() = 0; + + // determine the right-most border of the last column which is + // at least partially visible + _rCellArea.Right() = m_nRowHeaderWidthPixel; + if ( !m_aAccColumnWidthsPixel.empty() ) + { + // the number of pixels which are scroll out of the left hand + // side of the window + long nScrolledOutLeft = m_nLeftColumn == 0 ? 0 : m_aAccColumnWidthsPixel[ m_nLeftColumn - 1 ]; + + ArrayOfLong::const_reverse_iterator loop = m_aAccColumnWidthsPixel.rbegin(); + do + { + _rCellArea.Right() = *loop++ - nScrolledOutLeft + m_nRowHeaderWidthPixel; + } + while ( ( loop != m_aAccColumnWidthsPixel.rend() ) + && ( *loop - nScrolledOutLeft >= _rCellArea.Right() ) + ); + } + // so far, _rCellArea.Right() denotes the first pixel *after* the cell area + --_rCellArea.Right(); + + // determine the last row which is at least partially visible + _rCellArea.Bottom() = + m_nColHeaderHeightPixel + + impl_getVisibleRows( true ) * m_nRowHeightPixel + - 1; + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const + { + DBG_CHECK_ME(); + + impl_getAllVisibleCellsArea( _rCellArea ); + _rCellArea.Left() = m_nRowHeaderWidthPixel; + _rCellArea.Top() = m_nColHeaderHeightPixel; + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_ni_updateCachedModelValues() + { + m_nRowHeightPixel = 15; + m_nColHeaderHeightPixel = 0; + m_nRowHeaderWidthPixel = 0; + m_pInputHandler.reset(); + m_nColumnCount = m_nRowCount = 0; + + m_nRowHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getRowHeight() ), MAP_100TH_MM ).Height(); + if ( m_pModel->hasColumnHeaders() ) + m_nColHeaderHeightPixel = m_rAntiImpl.LogicToPixel( Size( 0, m_pModel->getColumnHeaderHeight() ), MAP_100TH_MM ).Height(); + if ( m_pModel->hasRowHeaders() ) + m_nRowHeaderWidthPixel = m_rAntiImpl.LogicToPixel( Size( m_pModel->getRowHeaderWidth(), 0 ), MAP_100TH_MM ).Width(); + + impl_ni_updateColumnWidths(); + + m_pInputHandler = m_pModel->getInputHandler(); + if ( !m_pInputHandler ) + m_pInputHandler.reset( new DefaultInputHandler ); + + m_nColumnCount = m_pModel->getColumnCount(); + m_nRowCount = m_pModel->getRowCount(); + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_ni_updateColumnWidths() + { + m_aColumnWidthsPixel.resize( 0 ); + m_aAccColumnWidthsPixel.resize( 0 ); + if ( !m_pModel ) + return; + + TableSize colCount = m_pModel->getColumnCount(); + m_aColumnWidthsPixel.reserve( colCount ); + m_aAccColumnWidthsPixel.reserve( colCount ); + long accumulatedPixelWidth = 0; + for ( ColPos col = 0; col < colCount; ++col ) + { + PColumnModel pColumn = m_pModel->getColumnModel( col ); + DBG_ASSERT( !!pColumn, "TableControl_Impl::impl_ni_updateColumnWidths: invalid column returned by the model!" ); + if ( !pColumn ) + continue; + + TableMetrics colWidth = pColumn->getWidth(); + DBG_ASSERT( ( colWidth == COLWIDTH_FIT_TO_VIEW ) || ( colWidth > 0 ), + "TableControl_Impl::impl_ni_updateColumnWidths: invalid column width!" ); + + long pixelWidth = 0; + if ( colWidth == COLWIDTH_FIT_TO_VIEW ) + { + // TODO + DBG_ERROR( "TableControl_Impl::impl_ni_updateColumnWidths: COLWIDTH_FIT_TO_VIEW not implemented, yet!" ); + } + else + { + pixelWidth = m_rAntiImpl.LogicToPixel( Size( colWidth, 0 ), MAP_100TH_MM ).Width(); + } + + m_aColumnWidthsPixel.push_back( pixelWidth ); + + m_aAccColumnWidthsPixel.push_back( accumulatedPixelWidth += pixelWidth ); + } + } + + //-------------------------------------------------------------------- + namespace + { + //................................................................ + /// determines whether a scrollbar is needed for the given values + bool lcl_determineScrollbarNeed( ScrollbarVisibility _eVisibility, + long _nVisibleUnits, long _nRange ) + { + if ( _eVisibility == ScrollbarShowNever ) + return false; + if ( _eVisibility == ScrollbarShowAlways ) + return true; + return _nVisibleUnits > _nRange; + } + + //................................................................ + void lcl_setButtonRepeat( Window& _rWindow, ULONG _nDelay ) + { + AllSettings aSettings = _rWindow.GetSettings(); + MouseSettings aMouseSettings = aSettings.GetMouseSettings(); + + aMouseSettings.SetButtonRepeat( _nDelay ); + aSettings.SetMouseSettings( aMouseSettings ); + + _rWindow.SetSettings( aSettings, TRUE ); + } + + //................................................................ + void lcl_updateScrollbar( Window& _rParent, ScrollBar*& _rpBar, + ScrollbarVisibility _eVisibility, long _nVisibleUnits, + long _nPosition, long _nLineSize, long _nRange, + bool _bHorizontal, const Link& _rScrollHandler ) + { + // do we need the scrollbar? + bool bNeedBar = lcl_determineScrollbarNeed( _eVisibility, _nVisibleUnits, _nRange ); + + // do we currently have the scrollbar? + bool bHaveBar = _rpBar != NULL; + + // do we need to correct the scrollbar visibility? + if ( bHaveBar && !bNeedBar ) + { + DELETEZ( _rpBar ); + } + else if ( !bHaveBar && bNeedBar ) + { + _rpBar = new ScrollBar( + &_rParent, + WB_DRAG | ( _bHorizontal ? WB_HSCROLL : WB_VSCROLL ) + ); + _rpBar->SetScrollHdl( _rScrollHandler ); + // get some speed into the scrolling .... + lcl_setButtonRepeat( *_rpBar, 0 ); + } + + if ( _rpBar ) + { + _rpBar->SetRange( Range( 0, _nRange ) ); + _rpBar->SetVisibleSize( _nVisibleUnits ); + _rpBar->SetPageSize( _nVisibleUnits ); + _rpBar->SetLineSize( _nLineSize ); + _rpBar->SetThumbPos( _nPosition ); + _rpBar->Show(); + } + } + + //................................................................ + /** returns the number of rows fitting into the given range, + for the given row height. Partially fitting rows are counted, too, if the + respective parameter says so. + */ + TableSize lcl_getRowsFittingInto( long _nOverallHeight, long _nRowHeightPixel, bool _bAcceptPartialRow = false ) + { + return _bAcceptPartialRow + ? ( _nOverallHeight + ( _nRowHeightPixel - 1 ) ) / _nRowHeightPixel + : _nOverallHeight / _nRowHeightPixel; + } + + //................................................................ + /** returns the number of columns fitting into the given area, + with the first visible column as given. Partially fitting columns are counted, too, + if the respective parameter says so. + */ + TableSize lcl_getColumnsVisibleWithin( const Rectangle& _rArea, ColPos _nFirstVisibleColumn, + const TableControl_Impl& _rControl, bool _bAcceptPartialRow ) + { + TableSize visibleColumns = 0; + TableColumnGeometry aColumn( _rControl, _rArea, _nFirstVisibleColumn ); + while ( aColumn.isValid() ) + { + if ( !_bAcceptPartialRow ) + if ( aColumn.getRect().Right() > _rArea.Right() ) + // this column is only partially visible, and this is not allowed + break; + + aColumn.moveRight(); + ++visibleColumns; + } + return visibleColumns; + } + + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_ni_updateScrollbars() + { + TempHideCursor aHideCursor( *this ); + + // the width/height of a scrollbar, needed several times below + long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize(); + if ( m_rAntiImpl.IsZoom() ) + nScrollbarMetrics = (long)( nScrollbarMetrics * (double)m_rAntiImpl.GetZoom() ); + + // determine the playground for the data cells (excluding headers) + // TODO: what if the control is smaller than needed for the headers/scrollbars? + Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() ); + aDataCellPlayground.Left() = m_nRowHeaderWidthPixel; + aDataCellPlayground.Top() = m_nColHeaderHeightPixel; + + // do we need a vertical scrollbar? + bool bFirstRoundVScrollNeed = false; + if ( lcl_determineScrollbarNeed( + m_pModel->getVerticalScrollbarVisibility(aDataCellPlayground.GetHeight(), m_nRowHeightPixel*m_nRowCount), + lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ), + m_nRowCount ) ) + { + aDataCellPlayground.Right() -= nScrollbarMetrics; + bFirstRoundVScrollNeed = true; + } + // do we need a horizontal scrollbar? + if ( lcl_determineScrollbarNeed( + m_pModel->getHorizontalScrollbarVisibility(aDataCellPlayground.GetWidth(), m_aAccColumnWidthsPixel[m_nColumnCount-1]), + lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false ), + m_nColumnCount ) ) + { + aDataCellPlayground.Bottom() -= nScrollbarMetrics; + + // now that we just found that we need a horizontal scrollbar, + // the need for a vertical one may have changed, since the horizontal + // SB might just occupy enough space so that not all rows do fit + // anymore + if ( !bFirstRoundVScrollNeed && lcl_determineScrollbarNeed( + m_pModel->getVerticalScrollbarVisibility(aDataCellPlayground.GetHeight(),m_nRowHeightPixel*m_nRowCount), + lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ), + m_nRowCount ) ) + { + aDataCellPlayground.Right() -= nScrollbarMetrics; + } + } + else + { + Size regionWithoutHeader = m_rAntiImpl.PixelToLogic(Size(aDataCellPlayground.Right() - aDataCellPlayground.Left(),0),MAP_100TH_MM); + TableMetrics nColWidth = regionWithoutHeader.Width()/m_nColumnCount; + for ( ColPos col = 0; col < m_nColumnCount; ++col ) + m_pModel->getColumnModel(col)->setWidth(nColWidth); + m_rAntiImpl.SetModel(m_pModel); + } + + // create or destroy the vertical scrollbar, as needed + lcl_updateScrollbar( + m_rAntiImpl, + m_pVScroll, + m_pModel->getVerticalScrollbarVisibility(aDataCellPlayground.GetHeight(),m_nRowHeightPixel*m_nRowCount), + lcl_getRowsFittingInto( aDataCellPlayground.GetHeight(), m_nRowHeightPixel ), + // visible units + m_nTopRow, // current position + 1, // line size + m_nRowCount, // range + false, // vertical + LINK( this, TableControl_Impl, OnScroll ) // scroll handler + ); + // position it + if ( m_pVScroll ) + { + Rectangle aScrollbarArea( + Point( aDataCellPlayground.Right() + 1, 0 ), + Size( nScrollbarMetrics, aDataCellPlayground.Bottom() + 1 ) + ); + m_pVScroll->SetPosSizePixel( + aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() ); + } + + // create or destroy the horizontal scrollbar, as needed + lcl_updateScrollbar( + m_rAntiImpl, + m_pHScroll, + m_pModel->getHorizontalScrollbarVisibility(aDataCellPlayground.GetWidth(), m_aAccColumnWidthsPixel[m_nColumnCount-1]), + lcl_getColumnsVisibleWithin( aDataCellPlayground, m_nLeftColumn, *this, false ), + // visible units + m_nLeftColumn, // current position + 1, // line size + m_nColumnCount, // range + true, // horizontal + LINK( this, TableControl_Impl, OnScroll ) // scroll handler + ); + // position it + if ( m_pHScroll ) + { + Rectangle aScrollbarArea( + Point( 0, aDataCellPlayground.Bottom() + 1 ), + Size( aDataCellPlayground.Right() + 1, nScrollbarMetrics ) + ); + m_pHScroll->SetPosSizePixel( + aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() ); + } + + // the corner window connecting the two scrollbars in the lower right corner + bool bHaveScrollCorner = NULL != m_pScrollCorner; + bool bNeedScrollCorner = ( NULL != m_pHScroll ) && ( NULL != m_pVScroll ); + if ( bHaveScrollCorner && !bNeedScrollCorner ) + { + DELETEZ( m_pScrollCorner ); + } + else if ( !bHaveScrollCorner && bNeedScrollCorner ) + { + m_pScrollCorner = new ScrollBarBox( &m_rAntiImpl ); + m_pScrollCorner->SetSizePixel( Size( nScrollbarMetrics, nScrollbarMetrics ) ); + m_pScrollCorner->SetPosPixel( Point( aDataCellPlayground.Right() + 1, aDataCellPlayground.Bottom() + 1 ) ); + m_pScrollCorner->Show(); + } + + // resize the data window + m_pDataWindow->SetSizePixel( Size( + aDataCellPlayground.GetWidth() + m_nRowHeaderWidthPixel, + aDataCellPlayground.GetHeight() + m_nColHeaderHeightPixel + ) ); + } + + //-------------------------------------------------------------------- + void TableControl_Impl::onResize() + { + DBG_CHECK_ME(); + impl_ni_updateScrollbars(); + //Rectangle aAllCells; + // impl_getAllVisibleCellsArea( aAllCells ); + //m_pSelEngine->SetVisibleArea(aAllCells); + } + + //-------------------------------------------------------------------- + void TableControl_Impl::doPaintContent( const Rectangle& _rUpdateRect ) + { + DBG_CHECK_ME(); + + if ( !getModel() ) + return; + + PTableRenderer pRenderer = getModel()->getRenderer(); + DBG_ASSERT( !!pRenderer, "TableDataWindow::Paint: invalid renderer!" ); + if ( !pRenderer ) + return; + + // our current style settings, to be passed to the renderer + const StyleSettings& rStyle = m_rAntiImpl.GetSettings().GetStyleSettings(); + + // the area occupied by all (at least partially) visible cells, including + // headers + Rectangle aAllCellsWithHeaders; + impl_getAllVisibleCellsArea( aAllCellsWithHeaders ); + + m_nRowCount = m_pModel->getRowCount(); + // ............................ + // draw the header column area + if ( getModel()->hasColumnHeaders() ) + { + TableRowGeometry aHeaderRow( *this, Rectangle( Point( 0, 0 ), + aAllCellsWithHeaders.BottomRight() ), ROW_COL_HEADERS ); + pRenderer->PaintHeaderArea( + *m_pDataWindow, aHeaderRow.getRect(), true, false, rStyle + ); + // Note that strictly, aHeaderRow.getRect() also contains the intersection between column + // and row header area. However, below we go to paint this intersection, again, + // so this hopefully doesn't hurt if we already paint it here. + + for ( TableCellGeometry aCell( aHeaderRow, m_nLeftColumn ); + aCell.isValid(); + aCell.moveRight() + ) + { + if ( _rUpdateRect.GetIntersection( aCell.getRect() ).IsEmpty() ) + continue; + + bool isActiveColumn = ( aCell.getColumn() == getCurColumn() ); + bool isSelectedColumn = false; + pRenderer->PaintColumnHeader( aCell.getColumn(), isActiveColumn, isSelectedColumn, + *m_pDataWindow, aCell.getRect(), rStyle ); + } + } + + // the area occupied by the row header, if any + Rectangle aRowHeaderArea; + if ( getModel()->hasRowHeaders() ) + { + aRowHeaderArea = aAllCellsWithHeaders; + aRowHeaderArea.Right() = m_nRowHeaderWidthPixel - 1; + aRowHeaderArea.Bottom() = m_nRowHeightPixel * m_nRowCount + m_nColHeaderHeightPixel - 1; + pRenderer->PaintHeaderArea( + *m_pDataWindow, aRowHeaderArea, false, true, rStyle + ); + // Note that strictly, aRowHeaderArea also contains the intersection between column + // and row header area. However, below we go to paint this intersection, again, + // so this hopefully doesn't hurt if we already paint it here. + + if ( getModel()->hasColumnHeaders() ) + { + TableCellGeometry aIntersection( *this, Rectangle( Point( 0, 0 ), + aAllCellsWithHeaders.BottomRight() ), COL_ROW_HEADERS, ROW_COL_HEADERS ); + pRenderer->PaintHeaderArea( + *m_pDataWindow, aIntersection.getRect(), true, true, rStyle + ); + } + } + + // ............................ + // draw the table content row by row + + TableSize colCount = getModel()->getColumnCount(); + + // paint all rows + Rectangle aAllDataCellsArea; + 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(); + //if the vector is empty, fill it with empty data, so the table can be painted + if(aCellContent.empty()) + { + std::vector<rtl::OUString> emptyCells; + while(m_nRowCount!=0) + { + aCellContent.push_back(emptyCells); + --m_nRowCount; + } + } + 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>::iterator itRowName = aRowHeaderContent.begin(); + + if(m_pModel->hasRowHeaders()) + { + aRowHeaderContent = m_pModel->getRowHeaderName(); + //if the vector is empty, fill it with empty strings, so the table can be painted + if(aRowHeaderContent.empty()) + { + while(m_nRowCount!=0) + { + aRowHeaderContent.push_back(rtl::OUString::createFromAscii("")); + --m_nRowCount; + } + } + itRowName = aRowHeaderContent.begin()+m_nTopRow; + } + for ( TableRowGeometry aRowIterator( *this, aAllCellsWithHeaders, getTopRow() ); + aRowIterator.isValid(); + aRowIterator.moveDown() ) + { + if ( _rUpdateRect.GetIntersection( aRowIterator.getRect() ).IsEmpty() ) + { + if(m_pModel->hasRowHeaders()) + ++itRowName; + ++it; + continue; + } + bool isActiveRow = ( aRowIterator.getRow() == getCurRow() ); + bool isSelectedRow = false; + if(!m_nRowSelected.empty()) + { + for(std::vector<RowPos>::iterator itSel=m_nRowSelected.begin(); + itSel!=m_nRowSelected.end();++itSel) + { + if(*itSel == aRowIterator.getRow()) + isSelectedRow = true; + } + } + std::vector<rtl::OUString> aCellData; + if(it != aCellContent.end()) + { + aCellData = *it; + ++it; + } + ::std::vector<rtl::OUString>::iterator iter = aCellData.begin()+m_nLeftColumn; + + // give the redenderer a chance to prepare the row + pRenderer->PrepareRow( aRowIterator.getRow(), isActiveRow, isSelectedRow, + *m_pDataWindow, aRowIterator.getRect().GetIntersection( aAllDataCellsArea ), rStyle ); + + // paint the row header + if ( m_pModel->hasRowHeaders() ) + { + rtl::OUString rowHeaderName; + if(itRowName != aRowHeaderContent.end()) + { + rowHeaderName = *itRowName; + ++itRowName; + } + Rectangle aCurrentRowHeader( aRowHeaderArea.GetIntersection( aRowIterator.getRect() ) ); + pRenderer->PaintRowHeader( isActiveRow, isSelectedRow, *m_pDataWindow, aCurrentRowHeader, + rStyle, rowHeaderName ); + } + if ( !colCount ) + continue; + + // paint all cells in this row + for ( TableCellGeometry aCell( aRowIterator, m_nLeftColumn ); + aCell.isValid(); + aCell.moveRight() + ) + { + // if ( _rUpdateRect.GetIntersection( aCell.getRect() ).IsEmpty() ) + // continue; + + //bool isActiveCell = isActiveRow && ( aCell.getColumn() == getCurColumn() ); + bool isSelectedColumn = false; + rtl::OUString cellData; + if(aCellData.empty()) + cellData=rtl::OUString::createFromAscii(""); + else if(iter != aCellData.end()) + { + cellData = *iter; + ++iter; + } + pRenderer->PaintCell( aCell.getColumn(), isSelectedRow || isSelectedColumn, isActiveRow, + *m_pDataWindow, aCell.getRect(), rStyle, cellData ); + } + } + } + + //-------------------------------------------------------------------- + void TableControl_Impl::hideCursor() + { + DBG_CHECK_ME(); + + if ( ++m_nCursorHidden == 1 ) + impl_ni_doSwitchCursor( false ); + } + + //-------------------------------------------------------------------- + void TableControl_Impl::showCursor() + { + DBG_CHECK_ME(); + + DBG_ASSERT( m_nCursorHidden > 0, "TableControl_Impl::showCursor: cursor not hidden!" ); + if ( --m_nCursorHidden == 0 ) + impl_ni_doSwitchCursor( true ); + } + + //-------------------------------------------------------------------- + bool TableControl_Impl::dispatchAction( TableControlAction _eAction ) + { + DBG_CHECK_ME(); + + bool bSuccess = false; + Rectangle rCells; + switch ( _eAction ) + { + case cursorDown: + if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + { + //if other rows already selected, deselect them + if(m_nRowSelected.size()>0) + { + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + it!=m_nRowSelected.end();++it) + { + invalidateSelectedRow(*it,rCells); + m_pDataWindow->Invalidate(rCells); + } + m_nRowSelected.clear(); + } + if(m_nCurRow < m_nRowCount-1) + { + ++m_nCurRow; + m_nRowSelected.push_back(m_nCurRow); + } + else + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + ensureVisible(m_nCurColumn,m_nCurRow,false); + bSuccess = true; + } + else + { + if ( m_nCurRow < m_nRowCount - 1 ) + bSuccess = goTo( m_nCurColumn, m_nCurRow + 1 ); + } + break; + + case cursorUp: + if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + { + if(m_nRowSelected.size()>0) + { + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + it!=m_nRowSelected.end();++it) + { + invalidateSelectedRow(*it,rCells); + m_pDataWindow->Invalidate(rCells); + } + m_nRowSelected.clear(); + } + if(m_nCurRow>0) + { + --m_nCurRow; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + ensureVisible(m_nCurColumn,m_nCurRow,false); + bSuccess = true; + } + else + { + if ( m_nCurRow > 0 ) + bSuccess = goTo( m_nCurColumn, m_nCurRow - 1 ); + } + break; + case cursorLeft: + if ( m_nCurColumn > 0 ) + bSuccess = goTo( m_nCurColumn - 1, m_nCurRow ); + else + if ( ( m_nCurColumn == 0) && ( m_nCurRow > 0 ) ) + bSuccess = goTo( m_nColumnCount - 1, m_nCurRow - 1 ); + break; + + case cursorRight: + if ( m_nCurColumn < m_nColumnCount - 1 ) + bSuccess = goTo( m_nCurColumn + 1, m_nCurRow ); + else + if ( ( m_nCurColumn == m_nColumnCount - 1 ) && ( m_nCurRow < m_nRowCount - 1 ) ) + bSuccess = goTo( 0, m_nCurRow + 1 ); + break; + + case cursorToLineStart: + bSuccess = goTo( 0, m_nCurRow ); + break; + + case cursorToLineEnd: + bSuccess = goTo( m_nColumnCount - 1, m_nCurRow ); + break; + + case cursorToFirstLine: + bSuccess = goTo( m_nCurColumn, 0 ); + break; + + case cursorToLastLine: + bSuccess = goTo( m_nCurColumn, m_nRowCount - 1 ); + break; + + case cursorPageUp: + { + RowPos nNewRow = ::std::max( (RowPos)0, m_nCurRow - impl_getVisibleRows( false ) ); + bSuccess = goTo( m_nCurColumn, nNewRow ); + } + break; + + case cursorPageDown: + { + RowPos nNewRow = ::std::min( m_nRowCount - 1, m_nCurRow + impl_getVisibleRows( false ) ); + bSuccess = goTo( m_nCurColumn, nNewRow ); + } + break; + + case cursorTopLeft: + bSuccess = goTo( 0, 0 ); + break; + + case cursorBottomRight: + bSuccess = goTo( m_nColumnCount - 1, m_nRowCount - 1 ); + break; + + case cursorSelectRow: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + return bSuccess = false; + //pos is the position of the current row in the vector of selected rows, if current row is selected + int pos = getRowSelectedNumber(m_nRowSelected, m_nCurRow); + //if current row is selected, it should be deselected, when ALT+SPACE are pressed + if(pos>-1) + m_nRowSelected.erase(m_nRowSelected.begin()+pos); + //else select the row->put it in the vector + else + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + bSuccess = true; + } + break; + case cursorSelectRowUp: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + return bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + { + //if there are other selected rows, deselect them + return false; + } + else + { + //there are other selected rows + if(m_nRowSelected.size()>0) + { + //the anchor wasn't set -> a region is not selected, that's why clear all selection + //and select the current row + if(m_nAnchor==-1) + { + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + it!=m_nRowSelected.end();++it) + { + invalidateSelectedRow(*it,rCells); + m_pDataWindow->Invalidate(rCells); + } + m_nRowSelected.clear(); + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + else + { + //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected + int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow); + int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow-1); + if(prevRow>-1) + { + //if m_nCurRow isn't the upper one, can move up, otherwise not + if(m_nCurRow>0) + m_nCurRow--; + else + return bSuccess = true; + //if nextRow already selected, deselect it, otherwise select it + if(m_nRowSelected[nextRow] == m_nCurRow) + { + m_nRowSelected.erase(m_nRowSelected.begin()+prevRow); + invalidateSelectedRow(m_nCurRow+1, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + } + } + } + else + { + //if nothing is selected and the current row isn't the upper one + //select the current and one row above + //otherwise select only the upper row + if(m_nCurRow>0) + { + m_nRowSelected.push_back(m_nCurRow); + m_nCurRow--; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow+1, m_nCurRow, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + } + m_pSelEngine->SetAnchor(TRUE); + m_nAnchor = m_nCurRow; + ensureVisible(m_nCurColumn, m_nCurRow, false); + bSuccess = true; + } + } + break; + case cursorSelectRowDown: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + { + bSuccess = false; + } + else + { + if(m_nRowSelected.size()>0) + { + //the anchor wasn't set -> a region is not selected, that's why clear all selection + //and select the current row + if(m_nAnchor==-1) + { + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + it!=m_nRowSelected.end();++it) + { + invalidateSelectedRow(*it,rCells); + m_pDataWindow->Invalidate(rCells); + } + m_nRowSelected.clear(); + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + else + { + //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected + int prevRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow); + int nextRow = getRowSelectedNumber(m_nRowSelected, m_nCurRow+1); + if(prevRow>-1) + { + //if m_nCurRow isn't the last one, can move down, otherwise not + if(m_nCurRow<m_nRowCount) + m_nCurRow++; + else + return bSuccess = true; + //if net row already selected, deselect it, otherwise select it + if(m_nRowSelected[nextRow] == m_nCurRow) + { + m_nRowSelected.erase(m_nRowSelected.begin()+prevRow); + invalidateSelectedRow(m_nCurRow-1, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + } + } + } + else + { + //there wasn't any selection, select curennt and row beneath, otherwise onlyrow beneath + if(m_nCurRow<m_nRowCount-1) + { + m_nRowSelected.push_back(m_nCurRow); + m_nCurRow++; + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRegion(m_nCurRow-1, m_nCurRow, rCells); + } + else + { + m_nRowSelected.push_back(m_nCurRow); + invalidateSelectedRow(m_nCurRow, rCells); + } + } + m_pSelEngine->SetAnchor(TRUE); + m_nAnchor = m_nCurRow; + ensureVisible(m_nCurColumn, m_nCurRow, false); + bSuccess = true; + } + } + break; + case cursorSelectRowAreaTop: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + bSuccess = false; + else + { + //select the region between the current and the upper row + RowPos iter = m_nCurRow; + invalidateSelectedRegion(m_nCurRow, 0, rCells); + //put the rows in vector + while(iter>=0) + { + if(!isRowSelected(m_nRowSelected, iter)) + m_nRowSelected.push_back(iter); + --iter; + } + m_nCurRow = 0; + m_nAnchor = m_nCurRow; + m_pSelEngine->SetAnchor(TRUE); + ensureVisible(m_nCurColumn, 0, false); + bSuccess = true; + } + } + break; + case cursorSelectRowAreaBottom: + { + if(m_pSelEngine->GetSelectionMode() == NO_SELECTION) + return bSuccess = false; + else if(m_pSelEngine->GetSelectionMode() == SINGLE_SELECTION) + return bSuccess = false; + //select the region between the current and the last row + RowPos iter = m_nCurRow; + invalidateSelectedRegion(m_nCurRow, m_nRowCount-1, rCells); + //put the rows in the vector + while(iter<=m_nRowCount) + { + if(!isRowSelected(m_nRowSelected, iter)) + m_nRowSelected.push_back(iter); + ++iter; + } + m_nCurRow = m_nRowCount-1; + m_nAnchor = m_nCurRow; + m_pSelEngine->SetAnchor(TRUE); + ensureVisible(m_nCurColumn, m_nRowCount, false); + bSuccess = true; + } + break; + default: + DBG_ERROR( "TableControl_Impl::dispatchAction: unsupported action!" ); + } + return bSuccess; + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_ni_doSwitchCursor( bool _bShow ) + { + PTableRenderer pRenderer = !!m_pModel ? m_pModel->getRenderer() : PTableRenderer(); + if ( !!pRenderer ) + { + Rectangle aCellRect; + impl_getCellRect( m_nCurColumn, m_nCurRow, aCellRect ); + + // const StyleSettings& rStyle = m_rAntiImpl.GetSettings().GetStyleSettings(); + if ( _bShow ) + { + pRenderer->ShowCellCursor( *m_pDataWindow, aCellRect); + } + else + { + pRenderer->HideCellCursor( *m_pDataWindow, aCellRect); + } + } + } + + //-------------------------------------------------------------------- + void TableControl_Impl::impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const + { + DBG_CHECK_ME(); + + if ( !m_pModel + || ( COL_INVALID == _nColumn ) + || ( ROW_INVALID == _nRow ) + ) + { + _rCellRect.SetEmpty(); + return; + } + + DBG_ASSERT( ( _nColumn >= 0 ) && ( _nColumn < m_pModel->getColumnCount() ), + "TableControl_Impl::impl_getCellRect: invalid column index!" ); + DBG_ASSERT( ( _nRow >= 0 ) && ( _nRow < m_pModel->getRowCount() ), + "TableControl_Impl::impl_getCellRect: invalid row index!" ); + + Rectangle aAllCells; + impl_getAllVisibleCellsArea( aAllCells ); + + TableCellGeometry aCell( *this, aAllCells, _nColumn, _nRow ); + _rCellRect = aCell.getRect(); + } + //------------------------------------------------------------------------------- + RowPos TableControl_Impl::getCurrentRow(const Point& rPoint) + { + DBG_CHECK_ME(); + Rectangle rCellRect; + RowPos newRowPos = -2;//-1 is HeaderRow + ColPos newColPos = 0; + //To Do: when only row position needed, the second loop isn't necessary, Please proove this!!! + for(int i=0;i<m_nRowCount;i++) + { + for(int j=-1;j<m_nColumnCount;j++) + { + impl_getCellRect(j,i,rCellRect); + if((rPoint.X() >= rCellRect.Left() && rPoint.X() <= rCellRect.Right()) && rPoint.Y() >= rCellRect.Top() && rPoint.Y() <= rCellRect.Bottom()) + { + newRowPos = i; + newColPos = j; + if(newColPos == -1) + m_nCurColumn = 0; + else + m_nCurColumn = newColPos; + return newRowPos; + } + } + } + return newRowPos; + } + //------------------------------------------------------------------------------- + void TableControl_Impl::setCursorAtCurrentCell(const Point& rPoint) + { + DBG_CHECK_ME(); + hideCursor(); + Rectangle rCellRect; + RowPos newRowPos = -2;//-1 is HeaderRow + ColPos newColPos = 0; + //To Do: when only row position needed, the second loop isn't necessary, Please proove this!!! + for(int i=0;i<m_nRowCount;i++) + { + for(int j=-1;j<m_nColumnCount;j++) + { + impl_getCellRect(j,i,rCellRect); + if((rPoint.X() >= rCellRect.Left() && rPoint.X() <= rCellRect.Right()) && rPoint.Y() >= rCellRect.Top() && rPoint.Y() <= rCellRect.Bottom()) + { + newRowPos = i; + m_nCurRow = newRowPos; + newColPos = j; + if(newColPos == -1) + m_nCurColumn = 0; + else + m_nCurColumn = newColPos; + } + } + } + showCursor(); + } + + //------------------------------------------------------------------------------- + void TableControl_Impl::invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect) + { + DBG_CHECK_ME(); + Rectangle aAllCells; + //get the visible area of the table control and set the Left and right border of the region to be repainted + impl_getAllVisibleCellsArea( aAllCells ); + _rCellRect.Left() = aAllCells.Left(); + _rCellRect.Right() = aAllCells.Right(); + Rectangle rCells; + //if only one row is selected + if(_nPrevRow == _nCurRow) + { + impl_getCellRect(m_nCurColumn,_nCurRow,rCells); + _rCellRect.Top()=rCells.Top(); + _rCellRect.Bottom()=rCells.Bottom(); + } + //if the region is above the current row + else if(_nPrevRow < _nCurRow ) + { + impl_getCellRect(m_nCurColumn,_nPrevRow,rCells); + _rCellRect.Top()=rCells.Top(); + impl_getCellRect(m_nCurColumn,_nCurRow,rCells); + _rCellRect.Bottom()=rCells.Bottom(); + } + //if the region is beneath the current row + else + { + impl_getCellRect(m_nCurColumn,_nCurRow,rCells); + _rCellRect.Top()=rCells.Top(); + impl_getCellRect(m_nCurColumn,_nPrevRow,rCells); + _rCellRect.Bottom()=rCells.Bottom(); + } + m_pDataWindow->Invalidate(_rCellRect); + } + + //------------------------------------------------------------------------------- + //To Do: not really needed, because in method above one row can be invalidate. Please Prove this!!! + void TableControl_Impl::invalidateSelectedRow(RowPos _nCurRow, Rectangle& _rCellRect) + { + DBG_CHECK_ME(); + Rectangle aAllCells; + impl_getAllVisibleCellsArea( aAllCells ); + _rCellRect.Left() = aAllCells.Left(); + _rCellRect.Right() = aAllCells.Right(); + Rectangle rCells; + impl_getCellRect(m_nCurColumn,_nCurRow,rCells); + _rCellRect.Top()=rCells.Top(); + _rCellRect.Bottom()=rCells.Bottom(); + m_pDataWindow->Invalidate(_rCellRect); + } + //------------------------------------------------------------------------------- + //this method is to be called, when a new row is added + void TableControl_Impl::invalidateRow(RowPos _nRowPos, Rectangle& _rCellRect) + { + //DBG_CHECK_ME(); + TempHideCursor aHideCursor( *this ); + impl_getAllVisibleCellsArea( _rCellRect ); + TableRowGeometry _rRow( *this, _rCellRect, _nRowPos); + impl_ni_updateScrollbars(); + m_pDataWindow->Invalidate(_rRow.getRect()); + } + + //------------------------------------------------------------------------------- + std::vector<RowPos> TableControl_Impl::getSelectedRows() + { + return m_nRowSelected; + } + + void TableControl_Impl::removeSelectedRow(RowPos _nRowPos) + { + int i =0; + //if the row is selected, remove it from the selection vector + if(isRowSelected(m_nRowSelected, _nRowPos)) + { + if(m_nRowSelected.size()>1) + m_nRowSelected.erase(m_nRowSelected.begin()+_nRowPos); + else + m_nRowSelected.clear(); + } + //after removing a row, row positions must be updated, so selected rows could stay selected + if(m_nRowSelected.size()>1) + { + for(std::vector<RowPos>::iterator it=m_nRowSelected.begin();it!=m_nRowSelected.end();++it) + { + if(*it > _nRowPos) + m_nRowSelected[i]=*it-1; + ++i; + } + } + if(_nRowPos == 0) + m_nCurRow = 0; + else + m_nCurRow = _nRowPos-1; + } + //------------------------------------------------------------------------------- + void TableControl_Impl::invalidateRows(RowPos _nRowStart, Rectangle& _rCellRect) + { + //DBG_CHECK_ME(); + (void)_nRowStart; + (void)_rCellRect; + /*TempHideCursor aHideCursor(*this); + Rectangle aAllCells; + impl_getAllVisibleCellsArea( aAllCells ); + TableRowGeometry _rRow( *this, aAllCells, _nRowStart); + _rCellRect = _rRow.getRect(); + Rectangle rCells1; + impl_getCellRect(m_nCurColumn,m_nRowCount,rCells1); + _rCellRect.Bottom() = rCells1.Bottom();*/ + /*if(_nRowStart != _nRowEnd) + { + TableRowGeometry _rRow( *this, aAllCells, _nRowEnd); + _rCellRect.Bottom() = _rRow.getRect().Bottom(); + } + */ + //_rCellRect.Right() = aAllCells.Right(); + //_rCellRect.Left() = aAllCells.Left(); + //Rectangle rCells1; + //impl_getCellRect(m_nCurColumn,_nRowStart,rCells1); + //_rCellRect.Top()=rCells1.Top(); + //Rectangle rCells2; + //impl_getCellRect(m_nCurColumn,_nRowEnd,rCells2); + //_rCellRect.Bottom()=rCells2.Bottom(); + impl_ni_updateScrollbars(); + //m_pDataWindow->Invalidate(_rCellRect); + m_pDataWindow->Invalidate(); + } + + + //------------------------------------------------------------------------------- + bool TableControl_Impl::isClickInVisibleArea(const Point& rPoint) + { + DBG_CHECK_ME(); + long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize(); + //clickable area is in the visible table control area without the scrollbars + Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() ); + aDataCellPlayground.Top() = m_nColHeaderHeightPixel; + aDataCellPlayground.Right() -= nScrollbarMetrics; + aDataCellPlayground.Bottom() -= nScrollbarMetrics; + if((rPoint.X() >= aDataCellPlayground.Left() && rPoint.X() <= aDataCellPlayground.Right()) && rPoint.Y() >= aDataCellPlayground.Top() && rPoint.Y() <= aDataCellPlayground.Bottom()) + { + return true; + } + else + return false; + } + //-------------------------------------------------------------------- + TableSize TableControl_Impl::impl_getVisibleRows( bool _bAcceptPartialRow ) const + { + DBG_CHECK_ME(); + + DBG_ASSERT( m_pDataWindow, "TableControl_Impl::impl_getVisibleRows: no data window!" ); + + return lcl_getRowsFittingInto( + m_pDataWindow->GetOutputSizePixel().Height() - m_nColHeaderHeightPixel, + m_nRowHeightPixel, + _bAcceptPartialRow + ); + } + + //-------------------------------------------------------------------- + TableSize TableControl_Impl::impl_getVisibleColumns( bool _bAcceptPartialRow ) const + { + DBG_CHECK_ME(); + + DBG_ASSERT( m_pDataWindow, "TableControl_Impl::impl_getVisibleColumns: no data window!" ); + + return lcl_getColumnsVisibleWithin( + Rectangle( Point( 0, 0 ), m_pDataWindow->GetOutputSizePixel() ), + m_nLeftColumn, + *this, + _bAcceptPartialRow + ); + } + + //-------------------------------------------------------------------- + bool TableControl_Impl::goTo( ColPos _nColumn, RowPos _nRow ) + { + DBG_CHECK_ME(); + + // TODO: give veto listeners a chance + + if ( ( _nColumn < -1 ) || ( _nColumn >= m_nColumnCount ) + || ( _nRow < -1 ) || ( _nRow >= m_nRowCount ) + ) + return false; + + TempHideCursor aHideCursor( *this ); + m_nCurColumn = _nColumn; + m_nCurRow = _nRow; + + // ensure that the new cell is visible + ensureVisible( m_nCurColumn, m_nCurRow, false ); + + // TODO: invalidate all and new column/row header, if present, to enforce + // re-painting them + //if(!m_nRowSelected.empty()) + //{ + // Rectangle rCells; + // for(std::vector<RowPos>::iterator it=m_nRowSelected.begin(); + // it!=m_nRowSelected.end();++it) + // { + // invalidateSelectedRow(*it,rCells); + // } + // m_nRowSelected.clear(); + //} + // TODO: notify listeners about new position + return true; + } + + //-------------------------------------------------------------------- + void TableControl_Impl::ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility ) + { + DBG_CHECK_ME(); + DBG_ASSERT( ( _nColumn >= 0 ) && ( _nColumn < m_nColumnCount ) + && ( _nRow >= 0 ) && ( _nRow < m_nRowCount ), + "TableControl_Impl::ensureVisible: invalid coordinates!" ); + + TempHideCursor aHideCursor( *this ); + + if ( _nColumn < m_nLeftColumn ) + impl_ni_ScrollColumns( _nColumn - m_nLeftColumn ); + else + { + TableSize nVisibleColumns = impl_getVisibleColumns( _bAcceptPartialVisibility ); + if ( _nColumn > m_nLeftColumn + nVisibleColumns - 1 ) + { + impl_ni_ScrollColumns( _nColumn - ( m_nLeftColumn + nVisibleColumns - 1 ) ); + // TODO: since not all columns have the same width, this might in theory result + // in the column still not being visible. + } + } + + if ( _nRow < m_nTopRow ) + impl_ni_ScrollRows( _nRow - m_nTopRow ); + else + { + TableSize nVisibleRows = impl_getVisibleRows( _bAcceptPartialVisibility ); + if ( _nRow > m_nTopRow + nVisibleRows - 1 ) + impl_ni_ScrollRows( _nRow - ( m_nTopRow + nVisibleRows - 1 ) ); + } + } + + //-------------------------------------------------------------------- + TableSize TableControl_Impl::impl_ni_ScrollRows( TableSize _nRowDelta ) + { + // compute new top row + RowPos nNewTopRow = + ::std::max( + ::std::min( (RowPos)( m_nTopRow + _nRowDelta ), (RowPos)( m_nRowCount - 1 ) ), + (RowPos)0 + ); + + RowPos nOldTopRow = m_nTopRow; + m_nTopRow = nNewTopRow; + + // if updates are enabled currently, scroll the viewport + if ( m_rAntiImpl.IsUpdateMode() && ( m_nTopRow != nOldTopRow ) ) + { + DBG_SUSPEND_INV( INV_SCROLL_POSITION ); + TempHideCursor aHideCursor( *this ); + // TODO: call a onStartScroll at our listener (or better an own onStartScroll, + // which hides the cursor and then calls the listener) + // Same for onEndScroll + + // scroll the view port, if possible + long nPixelDelta = m_nRowHeightPixel * ( m_nTopRow - nOldTopRow ); + + Rectangle aDataArea( Point( 0, m_nColHeaderHeightPixel ), m_pDataWindow->GetOutputSizePixel() ); + + if ( m_pDataWindow->GetBackground().IsScrollable() + && abs( nPixelDelta ) < aDataArea.GetHeight() + ) + { + m_pDataWindow->Scroll( 0, (long)-nPixelDelta, aDataArea, SCROLL_CLIP | SCROLL_UPDATE ); + } + else + m_pDataWindow->Invalidate( INVALIDATE_UPDATE ); + + // update the position at the vertical scrollbar + m_pVScroll->SetThumbPos( m_nTopRow ); + } + + return (TableSize)( m_nTopRow - nOldTopRow ); + } + + //-------------------------------------------------------------------- + TableSize TableControl_Impl::impl_ni_ScrollColumns( TableSize _nColumnDelta ) + { + // compute new left column + ColPos nNewLeftColumn = + ::std::max( + ::std::min( (ColPos)( m_nLeftColumn + _nColumnDelta ), (ColPos)( m_nColumnCount - 1 ) ), + (ColPos)0 + ); + + ColPos nOldLeftColumn = m_nLeftColumn; + m_nLeftColumn = nNewLeftColumn; + + // if updates are enabled currently, scroll the viewport + if ( m_rAntiImpl.IsUpdateMode() && ( m_nLeftColumn != nOldLeftColumn ) ) + { + DBG_SUSPEND_INV( INV_SCROLL_POSITION ); + TempHideCursor aHideCursor( *this ); + // TODO: call a onStartScroll at our listener (or better an own onStartScroll, + // which hides the cursor and then calls the listener) + // Same for onEndScroll + + // scroll the view port, if possible + Rectangle aDataArea( Point( m_nRowHeaderWidthPixel, 0 ), m_pDataWindow->GetOutputSizePixel() ); + + long nPixelDelta = + ( m_nLeftColumn > 0 ? m_aAccColumnWidthsPixel[ m_nLeftColumn - 1 ] : 0 ) + - ( nOldLeftColumn > 0 ? m_aAccColumnWidthsPixel[ nOldLeftColumn - 1 ] : 0 ); + + if ( m_pDataWindow->GetBackground().IsScrollable() + && abs( nPixelDelta ) < aDataArea.GetWidth() + ) + { + m_pDataWindow->Scroll( (long)-nPixelDelta, 0, aDataArea, SCROLL_CLIP | SCROLL_UPDATE ); + } + else + m_pDataWindow->Invalidate( INVALIDATE_UPDATE ); + + // update the position at the horizontal scrollbar + m_pHScroll->SetThumbPos( m_nLeftColumn ); + } + + return (TableSize)( m_nLeftColumn - nOldLeftColumn ); + } + + SelectionEngine* TableControl_Impl::getSelEngine() + { + return m_pSelEngine; + } + TableDataWindow* TableControl_Impl::getDataWindow() + { + return m_pDataWindow; + } + BOOL TableControl_Impl::isRowSelected(::std::vector<RowPos> selectedRows, RowPos current) + { + for(::std::vector<RowPos>::iterator it=selectedRows.begin(); + it!=selectedRows.end();++it) + { + if(*it == current) + return TRUE; + } + return FALSE; + } + + int TableControl_Impl::getRowSelectedNumber(::std::vector<RowPos> selectedRows, RowPos current) + { + int pos = -1; + int i = 0; + for(std::vector<RowPos>::iterator it=selectedRows.begin();it!=selectedRows.end();++it) + { + if(*it == current) + return pos = i; + ++i; + } + return pos; + } + + void TableControl_Impl::setCellContent(CellEntryType* pCellEntryType) + { + (void)pCellEntryType; + } + + //-------------------------------------------------------------------- + IMPL_LINK( TableControl_Impl, OnScroll, ScrollBar*, _pScrollbar ) + { + DBG_ASSERT( ( _pScrollbar == m_pVScroll ) || ( _pScrollbar == m_pHScroll ), + "TableControl_Impl::OnScroll: where did this come from?" ); + + if ( _pScrollbar == m_pVScroll ) + impl_ni_ScrollRows( _pScrollbar->GetDelta() ); + else + impl_ni_ScrollColumns( _pScrollbar->GetDelta() ); + + return 0L; + } + + //--------------------------------------------------------------------------------------- + TableFunctionSet::TableFunctionSet(TableControl_Impl* _pTableControl): + m_pTableControl( _pTableControl) + ,m_nCurrentRow (-2) + { + } + + TableFunctionSet::~TableFunctionSet() + { + } + + void TableFunctionSet::BeginDrag() + { + } + + void TableFunctionSet::CreateAnchor() + { + m_pTableControl->m_nAnchor = m_pTableControl->m_nCurRow; + } + + void TableFunctionSet::DestroyAnchor() + { + m_pTableControl->m_nAnchor = -1; + } + + BOOL TableFunctionSet::SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor) + { + BOOL bHandled = FALSE; + Rectangle rCells; + //curRow is the row where the mouse click happened, m_nCurRow is the last selected row, before the mouse click + RowPos curRow = m_pTableControl->getCurrentRow(rPoint); + if(curRow == -2) + return FALSE; + if( bDontSelectAtCursor ) + { + if(m_pTableControl->m_nRowSelected.size()>1) + m_pTableControl->m_pSelEngine->AddAlways(TRUE); + bHandled = TRUE; + } + else if(m_pTableControl->m_nAnchor == m_pTableControl->m_nCurRow) + { + //selecting region, + int diff = m_pTableControl->m_nCurRow - curRow; + //bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, m_pTableControl->m_nAnchor); + /* if(!isAlreadySelected && m_nCurrentRow != m_pTableControl->m_nCurRow) + m_pTableControl->m_nRowSelected.push_back(m_nAnchor);*/ + //selected region lies above the last selection + if( diff >= 0) + { + //put selected rows in vector + while(m_pTableControl->m_nAnchor>=curRow) + { + bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, m_pTableControl->m_nAnchor); + //if row isn't selected, put it in vector, otherwise don't put it there, because it will be twice there + if(!isAlreadySelected) + m_pTableControl->m_nRowSelected.push_back(m_pTableControl->m_nAnchor); + m_pTableControl->m_nAnchor--; + diff--; + } + m_pTableControl->m_nAnchor++; + } + //selected region lies beneath the last selected row + else + { + while(m_pTableControl->m_nAnchor<=curRow) + { + bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, m_pTableControl->m_nAnchor); + if(!isAlreadySelected) + m_pTableControl->m_nRowSelected.push_back(m_pTableControl->m_nAnchor); + m_pTableControl->m_nAnchor++; + diff++; + } + m_pTableControl->m_nAnchor--; + } + m_pTableControl->invalidateSelectedRegion(m_pTableControl->m_nCurRow, curRow, rCells); + bHandled = TRUE; + } + //no region selected + else + { + if(m_pTableControl->m_nRowSelected.empty()) + { + m_pTableControl->m_nRowSelected.push_back(curRow); + } + else + { + if(m_pTableControl->m_pSelEngine->GetSelectionMode()==SINGLE_SELECTION) + { + DeselectAll(); + m_pTableControl->m_nRowSelected.push_back(curRow); + } + else + { + bool isAlreadySelected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, curRow); + if(!isAlreadySelected) + m_pTableControl->m_nRowSelected.push_back(curRow); + } + } + if(m_pTableControl->m_nRowSelected.size()>1 && m_pTableControl->m_pSelEngine->GetSelectionMode()!=SINGLE_SELECTION) + m_pTableControl->m_pSelEngine->AddAlways(TRUE); + m_pTableControl->invalidateSelectedRow(curRow,rCells); + bHandled = TRUE; + } + m_pTableControl->m_nCurRow = curRow; + m_pTableControl->ensureVisible(m_pTableControl->m_nCurColumn,m_pTableControl->m_nCurRow,false); + return bHandled; + } + + BOOL TableFunctionSet::IsSelectionAtPoint( const Point& rPoint ) + { + m_pTableControl->m_pSelEngine->AddAlways(FALSE); + if(m_pTableControl->m_nRowSelected.empty()) + return FALSE; + else + { + RowPos curRow = m_pTableControl->getCurrentRow(rPoint); + m_pTableControl->m_nAnchor = -1; + bool selected = m_pTableControl->isRowSelected(m_pTableControl->m_nRowSelected, curRow); + m_nCurrentRow = curRow; + return selected; + } + } + + void TableFunctionSet::DeselectAtPoint( const Point& rPoint ) + { + (void)rPoint; + long pos = 0; + long i = 0; + Rectangle rCells; + for(std::vector<RowPos>::iterator it=m_pTableControl->m_nRowSelected.begin(); + it!=m_pTableControl->m_nRowSelected.end();++it) + { + if(*it == m_nCurrentRow) + { + pos = i; + m_pTableControl->invalidateSelectedRow(*it,rCells); + } + ++i; + } + m_pTableControl->m_nRowSelected.erase(m_pTableControl->m_nRowSelected.begin()+pos); + } + void TableFunctionSet::DeselectAll() + { + if(!m_pTableControl->m_nRowSelected.empty()) + { + Rectangle rCells; + for(std::vector<RowPos>::iterator it=m_pTableControl->m_nRowSelected.begin(); + it!=m_pTableControl->m_nRowSelected.end();++it) + { + m_pTableControl->invalidateSelectedRow(*it,rCells); + } + m_pTableControl->m_nRowSelected.clear(); + } + } + +//........................................................................ +} } // namespace svt::table +//........................................................................ diff --git a/svtools/source/table/tablecontrol_impl.hxx b/svtools/source/table/tablecontrol_impl.hxx new file mode 100644 index 000000000000..410bc8b4c3a1 --- /dev/null +++ b/svtools/source/table/tablecontrol_impl.hxx @@ -0,0 +1,342 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_TABLECONTROL_IMPL_HXX +#define SVTOOLS_TABLECONTROL_IMPL_HXX + +#ifndef SVTOOLS_INC_TABLE_TABLEMODEL_HXX +#include <svtools/table/tablemodel.hxx> +#endif + +#ifndef SVTOOLS_INC_TABLE_ABSTRACTTABLECONTROL_HXX +#include <svtools/table/abstracttablecontrol.hxx> +#endif + +#include <svtools/table/tablemodel.hxx> +#include <vector> +#include <vcl/seleng.hxx> + +class ScrollBar; +class ScrollBarBox; + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + typedef ::std::vector< long > ArrayOfLong; + + class TableControl; + class TableDataWindow; + class TableFunctionSet; + + //==================================================================== + //= TableControl_Impl + //==================================================================== + class TableControl_Impl : public IAbstractTableControl + { + friend class TableGeometry; + friend class TableRowGeometry; + friend class TableColumnGeometry; + friend class SuspendInvariants; + friend class TableFunctionSet; + private: + /// the control whose impl-instance we implemnt + TableControl& m_rAntiImpl; + /// the model of the table control + PTableModel m_pModel; + /// the input handler to use, usually the input handler as provided by ->m_pModel + PTableInputHandler m_pInputHandler; + /// the widths of the single columns, measured in pixel + ArrayOfLong m_aColumnWidthsPixel; + /** the accumulated widths of the single columns, i.e. their exclusive right borders, + <strong<not</strong> counting the space for a possible row header column + */ + ArrayOfLong m_aAccColumnWidthsPixel; + /// the height of a single row in the table, measured in pixels + long m_nRowHeightPixel; + /// the height of the column header row in the table, measured in pixels + long m_nColHeaderHeightPixel; + /// the width of the row header column in the table, measured in pixels + long m_nRowHeaderWidthPixel; + + /// the number of columns in the table control. Cached model value. + TableSize m_nColumnCount; + /// the number of rows in the table control. Cached model value. + TableSize m_nRowCount; + + ColPos m_nCurColumn; + RowPos m_nCurRow; + ColPos m_nLeftColumn; + RowPos m_nTopRow; + + sal_Int32 m_nCursorHidden; + + /** the window to contain all data content, including header bars + + The window's upper left corner is at position (0,0), relative to the + table control, which is the direct parent of the data window. + */ + TableDataWindow* m_pDataWindow; + /// the vertical scrollbar, if any + ScrollBar* m_pVScroll; + /// the horizontal scrollbar, if any + ScrollBar* m_pHScroll; + ScrollBarBox* m_pScrollCorner; + //selection engine - for determining selection range, e.g. single, multiple + SelectionEngine* m_pSelEngine; + //vector which contains the selected rows + std::vector<RowPos> m_nRowSelected; + //part of selection engine + TableFunctionSet* m_pTableFunctionSet; + //part of selection engine + RowPos m_nAnchor; + + + +#if DBG_UTIL + #define INV_SCROLL_POSITION 1 + /** represents a bitmask of invariants to check + + Actually, impl_checkInvariants checks more invariants than denoted in this + bit mask, but only those present here can be disabled temporarily. + */ + sal_Int32 m_nRequiredInvariants; +#endif + + public: + + + PTableModel getModel() const; + void setModel( PTableModel _pModel ); + + inline const PTableInputHandler& getInputHandler() const { return m_pInputHandler; } + + inline ColPos getCurColumn() const { return m_nCurColumn; } + inline RowPos getCurRow() const { return m_nCurRow; } + inline void setCurRow(RowPos curRow){ m_nCurRow = curRow; } + inline RowPos getTopRow() const { return m_nTopRow; } + + inline long getColHeaderHightPixel() const { return m_nColHeaderHeightPixel; } + + inline const TableControl& getAntiImpl() const { return m_rAntiImpl; } + inline TableControl& getAntiImpl() { return m_rAntiImpl; } + void setCellContent(CellEntryType* pCellEntryType); + + public: + TableControl_Impl( TableControl& _rAntiImpl ); + ~TableControl_Impl(); + +#if DBG_UTIL + const sal_Char* impl_checkInvariants() const; +#endif + /** to be called when the anti-impl instance has been resized + */ + void onResize(); + + /** paints the table control content which intersects with the given rectangle + */ + void doPaintContent( const Rectangle& _rUpdateRect ); + + /** moves the cursor to the cell with the given coordinates + + To ease the caller's code, the coordinates must not necessarily denote a + valid position. If they don't, <FALSE/> will be returned. + */ + bool goTo( ColPos _nColumn, RowPos _nRow ); + + /** ensures that the given coordinate is visible + @param _nColumn + the column position which should be visible. Must be non-negative, and smaller + than the column count. + @param _nRow + the row position which should be visibleMust be non-negative, and smaller + than the row count. + @param _bAcceptPartialVisibility + <TRUE/> if it's okay that the given cooordinate is only partially visible + */ + void ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility ); + /** returns the row, which contains the input point*/ + RowPos getCurrentRow (const Point& rPoint); + + void setCursorAtCurrentCell(const Point& rPoint); + /** proves whether the vector with the selected rows contains the current row*/ + BOOL isRowSelected(::std::vector<RowPos> selectedRows, RowPos current); + /** returns the position of the current row in the selecttion vector */ + int getRowSelectedNumber(::std::vector<RowPos> selectedRows, RowPos current); + /** _rCellRect contains the region, which should be invalidate after some action e.g. selectiong row*/ + void invalidateSelectedRegion(RowPos _nPrevRow, RowPos _nCurRow, Rectangle& _rCellRect ); + /** _rCellRect contains the region, which should be invalidate after some action e.g. selectiong row*/ + //vielleicht kann man mit den anderen verschmelzen, mit einer berprfung ob prev==curr? + void invalidateSelectedRow( RowPos _nCurRow, Rectangle& _rCellRect ); + /** 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(); + /** updates the vector, which contains the selected rows after removing the row nRowPos*/ + void removeSelectedRow(RowPos _nRowPos); + void invalidateRows(RowPos _nRowStart, Rectangle& _rCellRect ); + //virtual void DoubleClick(); + + // IAbstractTableControl + virtual void hideCursor(); + virtual void showCursor(); + virtual bool dispatchAction( TableControlAction _eAction ); + virtual bool isClickInVisibleArea(const Point& rPoint); + 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 + account the the fact that there might be less columns than would normally + find room in the control. + + As a result of respecting the partial visibility of rows and columns, + the returned area might be larger than the data window's output size. + */ + void impl_getAllVisibleCellsArea( Rectangle& _rCellArea ) const; + + /** retrieves the area occupied by all (at least partially) visible data cells. + + Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea, + minus the row and column header areas. + */ + void impl_getAllVisibleDataCellArea( Rectangle& _rCellArea ) const; + + /** returns the number of visible rows. + + @param _bAcceptPartialRow + specifies whether a possible only partially visible last row is + counted, too. + */ + TableSize impl_getVisibleRows( bool _bAcceptPartialRow ) const; + + /** returns the number of visible columns + + The value may change with different horizontal scroll positions, as + different columns have different widths. For instance, if your control is + 100 pixels wide, and has three columns of width 50, 50, 100, respectively, + then this method will return either "2" or "1", depending on which column + is the first visible one. + + @param _bAcceptPartialRow + specifies whether a possible only partially visible last row is + counted, too. + */ + TableSize impl_getVisibleColumns( bool _bAcceptPartialRow ) const; + + /** determines the rectangle occupied by the given cell + */ + void impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const; + + /** updates all cached model values + + 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_updateCachedModelValues(); + + /** updates ->m_aColumnWidthsPixel with the current pixel widths of all model columns + + The method takes into account the current zoom factor and map mode of the table + control, plus any possible COLWIDTH_FIT_TO_VIEW widths in the model columns. + + 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_updateColumnWidths(); + + /** updates the scrollbars of the control + + The method is not bound to the classes public invariants, as it's used in + situations where the they must not necessarily be fullfilled. + + This includes both the existence of the scrollbars, and their + state. + */ + void impl_ni_updateScrollbars(); + + /** scrolls the view by the given number of rows + + The method is not bound to the classes public invariants, as it's used in + situations where the they must not necessarily be fullfilled. + + @return + the number of rows by which the viewport was scrolled. This may differ + from the given numbers to scroll in case the begin or the end of the + row range were reached. + */ + TableSize impl_ni_ScrollRows( TableSize _nRowDelta ); + + /** scrolls the view by the given number of columns + + The method is not bound to the classes public invariants, as it's used in + situations where the they must not necessarily be fullfilled. + + @return + the number of columns by which the viewport was scrolled. This may differ + from the given numbers to scroll in case the begin or the end of the + column range were reached. + */ + TableSize impl_ni_ScrollColumns( TableSize _nRowDelta ); + + DECL_LINK( OnScroll, ScrollBar* ); + }; + //see seleng.hxx, seleng.cxx, FunctionSet overwritables, part of selection engine + class TableFunctionSet : public FunctionSet + { + friend class TableDataWindow; + private: + TableControl_Impl* m_pTableControl; + RowPos m_nCurrentRow; + public: + TableFunctionSet(TableControl_Impl* _pTableControl); + virtual ~TableFunctionSet(); + + virtual void BeginDrag(); + virtual void CreateAnchor(); + virtual void DestroyAnchor(); + virtual BOOL SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor); + virtual BOOL IsSelectionAtPoint( const Point& rPoint ); + virtual void DeselectAtPoint( const Point& rPoint ); + virtual void DeselectAll(); + }; + + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_TABLECONTROL_IMPL_HXX diff --git a/svtools/source/table/tabledatawindow.cxx b/svtools/source/table/tabledatawindow.cxx new file mode 100644 index 000000000000..71a313bb2e00 --- /dev/null +++ b/svtools/source/table/tabledatawindow.cxx @@ -0,0 +1,81 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "svtools/table/tablecontrol.hxx" +#include "svtools/table/tabledatawindow.hxx" +#include "tablecontrol_impl.hxx" + +//........................................................................ +namespace svt { namespace table +{ + class TableControl_Impl; +//........................................................................ + + //==================================================================== + //= TableDataWindow + //==================================================================== + //-------------------------------------------------------------------- + TableDataWindow::TableDataWindow( TableControl_Impl& _rTableControl ) + :Window( &_rTableControl.getAntiImpl() ) + ,m_rTableControl ( _rTableControl ) + { + Color backgroundColor = m_rTableControl.getAntiImpl().GetSettings().GetStyleSettings().GetFieldColor(); + SetBackground( backgroundColor ); + SetControlBackground( backgroundColor ); + } + + //-------------------------------------------------------------------- + void TableDataWindow::Paint( const Rectangle& rUpdateRect ) + { + m_rTableControl.doPaintContent( rUpdateRect ); + } + void TableDataWindow::MouseMove( const MouseEvent& rMEvt ) + { + if ( !m_rTableControl.getInputHandler()->MouseMove( m_rTableControl, rMEvt ) ) + Window::MouseMove( rMEvt ); + } + void TableDataWindow::MouseButtonDown( const MouseEvent& rMEvt ) + { + if ( !m_rTableControl.getInputHandler()->MouseButtonDown( m_rTableControl, rMEvt ) ) + Window::MouseButtonDown( rMEvt ); + else + m_aMouseButtonDownHdl.Call( (MouseEvent*) &rMEvt); + m_rTableControl.getAntiImpl().LoseFocus(); + } + void TableDataWindow::MouseButtonUp( const MouseEvent& rMEvt ) + { + if ( !m_rTableControl.getInputHandler()->MouseButtonUp( m_rTableControl, rMEvt ) ) + Window::MouseButtonUp( rMEvt ); + else + m_aMouseButtonUpHdl.Call( (MouseEvent*) &rMEvt); + m_rTableControl.getAntiImpl().GetFocus(); + } + +//........................................................................ +} } // namespace svt::table +//........................................................................ diff --git a/svtools/source/table/tablegeometry.cxx b/svtools/source/table/tablegeometry.cxx new file mode 100644 index 000000000000..569e14c61726 --- /dev/null +++ b/svtools/source/table/tablegeometry.cxx @@ -0,0 +1,130 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "tablegeometry.hxx" +#include "tablecontrol_impl.hxx" + +#include <tools/debug.hxx> + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + //==================================================================== + //= TableRowGeometry + //==================================================================== + //-------------------------------------------------------------------- + TableRowGeometry::TableRowGeometry( const TableControl_Impl& _rControl, const Rectangle& _rBoundaries, + RowPos _nRow ) + :TableGeometry( _rControl, _rBoundaries ) + ,m_nRowPos( _nRow ) + { + if ( m_nRowPos == ROW_COL_HEADERS ) + { + DBG_ASSERT( m_rControl.m_pModel->hasColumnHeaders(), + "TableRowGeometry::TableRowGeometry: why asking for the geoemtry of the non-existent column header row?" ); + m_aRect.Top() = 0; + m_aRect.Bottom() = m_rControl.m_nColHeaderHeightPixel - 1; + } + else + { + if ( ( m_nRowPos >= m_rControl.m_nTopRow ) && ( m_nRowPos < m_rControl.m_pModel->getRowCount() ) ) + { + m_aRect.Top() = m_rControl.m_nColHeaderHeightPixel + ( m_nRowPos - m_rControl.m_nTopRow ) * m_rControl.m_nRowHeightPixel; + m_aRect.Bottom() = m_aRect.Top() + m_rControl.m_nRowHeightPixel - 1; + } + else + m_aRect.SetEmpty(); + } + } + + //-------------------------------------------------------------------- + bool TableRowGeometry::moveDown() + { + if ( ++m_nRowPos < m_rControl.m_pModel->getRowCount() ) + m_aRect.Move( 0, m_rControl.m_nRowHeightPixel ); + else + m_aRect.SetEmpty(); + return isValid(); + } + + //==================================================================== + //= TableColumnGeometry + //==================================================================== + //-------------------------------------------------------------------- + TableColumnGeometry::TableColumnGeometry( const TableControl_Impl& _rControl, const Rectangle& _rBoundaries, + ColPos _nCol ) + :TableGeometry( _rControl, _rBoundaries ) + ,m_nColPos( _nCol ) + { + if ( m_nColPos == COL_ROW_HEADERS ) + { + DBG_ASSERT( m_rControl.m_pModel->hasRowHeaders(), + "TableColumnGeometry::TableColumnGeometry: why asking for the geoemtry of the non-existent row header column?" ); + m_aRect.Left() = 0; + m_aRect.Right() = m_rControl.m_nRowHeaderWidthPixel - 1; + } + else + { + ColPos nLeftColumn = m_rControl.m_nLeftColumn; + if ( ( m_nColPos >= nLeftColumn ) && ( m_nColPos < (ColPos)m_rControl.m_aColumnWidthsPixel.size() ) ) + { + m_aRect.Left() = m_rControl.m_nRowHeaderWidthPixel; + // TODO: take into account any possibly frozen columns + + for ( ColPos col = nLeftColumn; col < m_nColPos; ++col ) + m_aRect.Left() += m_rControl.m_aColumnWidthsPixel[ col ]; + m_aRect.Right() = m_aRect.Left() + m_rControl.m_aColumnWidthsPixel[ m_nColPos ] - 1; + } + else + m_aRect.SetEmpty(); + } + } + + //-------------------------------------------------------------------- + bool TableColumnGeometry::moveRight() + { + DBG_ASSERT( m_nColPos != COL_ROW_HEADERS, "TableColumnGeometry::moveRight: cannot move the row header column!" ); + // what would be COL_ROW_HEADERS + 1? + + if ( ++m_nColPos < (ColPos)m_rControl.m_aColumnWidthsPixel.size() ) + { + m_aRect.Left() = m_aRect.Right() + 1; + m_aRect.Right() += m_rControl.m_aColumnWidthsPixel[ m_nColPos ]; + } + else + m_aRect.SetEmpty(); + + return isValid(); + } + +//........................................................................ +} } // namespace svt::table +//........................................................................ diff --git a/svtools/source/table/tablegeometry.hxx b/svtools/source/table/tablegeometry.hxx new file mode 100644 index 000000000000..18b40c1e3781 --- /dev/null +++ b/svtools/source/table/tablegeometry.hxx @@ -0,0 +1,161 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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_TABLEGEOMETRY_HXX +#define SVTOOLS_TABLEGEOMETRY_HXX + +#ifndef SVTOOLS_INC_TABLE_TABLETYPES_HXX +#include <svtools/table/tabletypes.hxx> +#endif + +#ifndef _SV_GEN_HXX +#include <tools/gen.hxx> +#endif + +//........................................................................ +namespace svt { namespace table +{ +//........................................................................ + + class TableControl_Impl; + + //==================================================================== + //= TableGeometry + //==================================================================== + class TableGeometry + { + protected: + const TableControl_Impl& m_rControl; + const Rectangle& m_rBoundaries; + Rectangle m_aRect; + + protected: + TableGeometry( + const TableControl_Impl& _rControl, + const Rectangle& _rBoundaries + ) + :m_rControl( _rControl ) + ,m_rBoundaries( _rBoundaries ) + ,m_aRect( _rBoundaries ) + { + } + + public: + // attribute access + const TableControl_Impl& getControl() const { return m_rControl; } + + // status + const Rectangle& getRect() const { return m_aRect; } + bool isValid() const { return !m_aRect.GetIntersection( m_rBoundaries ).IsEmpty(); } + }; + + //==================================================================== + //= TableRowGeometry + //==================================================================== + class TableRowGeometry : public TableGeometry + { + protected: + RowPos m_nRowPos; + + public: + TableRowGeometry( + const TableControl_Impl& _rControl, + const Rectangle& _rBoundaries, + RowPos _nRow + ); + + // status + RowPos getRow() const { return m_nRowPos; } + // operations + bool moveDown(); + }; + + //==================================================================== + //= TableColumnGeometry + //==================================================================== + class TableColumnGeometry : public TableGeometry + { + protected: + ColPos m_nColPos; + + public: + TableColumnGeometry( + const TableControl_Impl& _rControl, + const Rectangle& _rBoundaries, + ColPos _nCol + ); + + // status + ColPos getCol() const { return m_nColPos; } + // operations + bool moveRight(); + }; + + //==================================================================== + //= TableCellGeometry + //==================================================================== + /** a helper representing geometry information of a cell + */ + class TableCellGeometry + { + private: + TableRowGeometry m_aRow; + TableColumnGeometry m_aCol; + + public: + TableCellGeometry( + const TableControl_Impl& _rControl, + const Rectangle& _rBoundaries, + ColPos _nCol, + RowPos _nRow + ) + :m_aRow( _rControl, _rBoundaries, _nRow ) + ,m_aCol( _rControl, _rBoundaries, _nCol ) + { + } + + TableCellGeometry( + const TableRowGeometry& _rRow, + ColPos _nCol + ) + :m_aRow( _rRow ) + ,m_aCol( _rRow.getControl(), _rRow.getRect(), _nCol ) + { + } + + inline Rectangle getRect() const { return m_aRow.getRect().GetIntersection( m_aCol.getRect() ); } + inline RowPos getRow() const { return m_aRow.getRow(); } + inline ColPos getColumn() const { return m_aCol.getCol(); } + inline bool isValid() const { return !getRect().IsEmpty(); } + + inline bool moveDown() {return m_aRow.moveDown(); } + inline bool moveRight() {return m_aCol.moveRight(); } + }; + +//........................................................................ +} } // namespace svt::table +//........................................................................ + +#endif // SVTOOLS_TABLEGEOMETRY_HXX diff --git a/svtools/source/uno/makefile.mk b/svtools/source/uno/makefile.mk index 76ab335d58d5..51e55a1f9123 100644 --- a/svtools/source/uno/makefile.mk +++ b/svtools/source/uno/makefile.mk @@ -1,4 +1,4 @@ - +#************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -55,6 +55,7 @@ SLOFILES= \ $(SLO)$/genericunodialog.obj \ $(SLO)$/generictoolboxcontroller.obj \ $(SLO)$/treecontrolpeer.obj \ + $(SLO)$/unocontroltablemodel.obj \ $(SLO)$/registerservices.obj\ $(SLO)$/contextmenuhelper.obj diff --git a/svtools/source/uno/unocontroltablemodel.cxx b/svtools/source/uno/unocontroltablemodel.cxx new file mode 100644 index 000000000000..e322dbb8f96e --- /dev/null +++ b/svtools/source/uno/unocontroltablemodel.cxx @@ -0,0 +1,812 @@ +/************************************************************************* + * + * 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: unocontroltablemodel.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 "unocontroltablemodel.hxx" +#include <com/sun/star/view/SelectionType.hpp> +#include "svtools/table/gridtablerenderer.hxx" +#include "svtools/table/defaultinputhandler.hxx" +#include "svtools/table/tablecontrol.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> + +using ::rtl::OUString; +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) + :m_nID( 0 ) + ,m_sName() + ,m_bIsResizable( false ) + ,m_nWidth( 10 * 100 ) // 1 cm + ,m_nMinWidth( 0 ) // no min width + ,m_nMaxWidth( 0 ) // no max width + { + //m_nID = m_xGridColumn->getIdentifier(); + //m_nWidth = m_xGridColumn->getColumnWidth(); + m_sName = m_xGridColumn->getTitle(); + } + + //-------------------------------------------------------------------- + ColumnID UnoControlTableColumn::getID() const + { + return m_nID; + } + + //-------------------------------------------------------------------- + bool UnoControlTableColumn::setID( const ColumnID _nID ) + { + // TODO: conflict check + + m_nID = _nID; + // TODO: notifications? + + return true; + } + + //-------------------------------------------------------------------- + String UnoControlTableColumn::getName() const + { + return m_sName; + } + + //-------------------------------------------------------------------- + void UnoControlTableColumn::setName( const String& _rName ) + { + m_sName = _rName; + // TODO: notifications? + } + + //-------------------------------------------------------------------- + bool UnoControlTableColumn::isResizable() const + { + return m_bIsResizable; + } + + //-------------------------------------------------------------------- + void UnoControlTableColumn::setResizable( bool _bResizable ) + { + m_bIsResizable = _bResizable; + // TODO: notifications? + } + + //-------------------------------------------------------------------- + TableMetrics UnoControlTableColumn::getWidth() const + { + return m_nWidth; + } + + //-------------------------------------------------------------------- + void UnoControlTableColumn::setWidth( TableMetrics _nWidth ) + { + m_nWidth = _nWidth; + // TODO: notifications? + } + + //-------------------------------------------------------------------- + TableMetrics UnoControlTableColumn::getMinWidth() const + { + return m_nMinWidth; + } + + //-------------------------------------------------------------------- + void UnoControlTableColumn::setMinWidth( TableMetrics _nMinWidth ) + { + m_nMinWidth = _nMinWidth; + // TODO: notifications? + } + + //-------------------------------------------------------------------- + TableMetrics UnoControlTableColumn::getMaxWidth() const + { + return m_nMaxWidth; + } + + //-------------------------------------------------------------------- + void UnoControlTableColumn::setMaxWidth( TableMetrics _nMaxWidth ) + { + m_nMaxWidth = _nMaxWidth; + // TODO: notifications? + } + + //==================================================================== + //= DefaultTableModel_Impl + //==================================================================== + struct UnoControlTableModel_Impl + { + ::std::vector< PColumnModel > aColumns; + TableSize nRowCount; + bool bHasColumnHeaders; + bool bHasRowHeaders; + PTableRenderer pRenderer; + PTableInputHandler pInputHandler; + TableMetrics nRowHeight; + TableMetrics nColumnHeaderHeight; + TableMetrics nRowHeaderWidth; + std::vector<rtl::OUString> aRowHeadersTitle; + std::vector<std::vector<rtl::OUString> > aCellContent; + + UnoControlTableModel_Impl() + :nRowCount ( 0 ) + ,bHasColumnHeaders ( false ) + ,bHasRowHeaders ( false ) + ,pRenderer ( ) + ,pInputHandler ( ) + ,nRowHeight ( 4 * 100 ) // 40 mm + ,nColumnHeaderHeight( 5 * 100 ) // 50 mm + ,nRowHeaderWidth ( 10 * 100 ) // 50 mm + ,aRowHeadersTitle ( 0 ) + ,aCellContent ( 0 ) + { + } + }; + + //==================================================================== + //= UnoControlTableModel + //==================================================================== + //-------------------------------------------------------------------- + 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->pRenderer.reset( new GridTableRenderer( *this ) ); + m_pImpl->pInputHandler.reset( new DefaultInputHandler ); + } + + //-------------------------------------------------------------------- + UnoControlTableModel::~UnoControlTableModel() + { + DELETEZ( m_pImpl ); + } + + //-------------------------------------------------------------------- + TableSize UnoControlTableModel::getColumnCount() const + { + m_pImpl->aColumns.resize( m_xColumnModel->getColumnCount()); + return (TableSize)m_pImpl->aColumns.size(); + } + + //-------------------------------------------------------------------- + TableSize UnoControlTableModel::getRowCount() const + { + return m_pImpl->nRowCount; + } + + //-------------------------------------------------------------------- + bool UnoControlTableModel::hasColumnHeaders() const + { + return m_pImpl->bHasColumnHeaders; + } + + //-------------------------------------------------------------------- + bool UnoControlTableModel::hasRowHeaders() const + { + return m_pImpl->bHasRowHeaders; + } + + //-------------------------------------------------------------------- + void UnoControlTableModel::setRowHeaders(bool _bRowHeaders) + { + m_pImpl->bHasRowHeaders = _bRowHeaders; + } + //-------------------------------------------------------------------- + void UnoControlTableModel::setColumnHeaders(bool _bColumnHeaders) + { + m_pImpl->bHasColumnHeaders = _bColumnHeaders; + } + + void UnoControlTableModel::setColumnCount(TableSize _nColCount) + { + m_pImpl->aColumns.resize( _nColCount); + } + //-------------------------------------------------------------------- + void UnoControlTableModel::setRowCount(TableSize _nRowCount) + { + m_pImpl->nRowCount = _nRowCount; + } + //-------------------------------------------------------------------- + bool UnoControlTableModel::isCellEditable( ColPos col, RowPos row ) const + { + (void)col; + (void)row; + return false; + } + + //-------------------------------------------------------------------- + void UnoControlTableModel::addTableModelListener( const PTableModelListener& listener ) + { + (void) listener; + //listener->onTableModelChanged(PTableModel(this)); + // TODO + DBG_ERROR( "DefaultTableModel::addTableModelListener: not yet implemented!" ); + } + + //-------------------------------------------------------------------- + void UnoControlTableModel::removeTableModelListener( const PTableModelListener& listener ) + { + (void)listener; + // TODO + DBG_ERROR( "DefaultTableModel::removeTableModelListener: not yet implemented!" ); + } + + //-------------------------------------------------------------------- + PColumnModel UnoControlTableModel::getColumnModel( ColPos column ) + { + DBG_ASSERT( ( column >= 0 ) && ( column < getColumnCount() ), + "DefaultTableModel::getColumnModel: invalid index!" ); + return m_pImpl->aColumns[ column ]; + } + + //-------------------------------------------------------------------- + PColumnModel UnoControlTableModel::getColumnModelByID( ColumnID id ) + { + (void)id; + // TODO + DBG_ERROR( "DefaultTableModel::getColumnModelByID: not yet implemented!" ); + return PColumnModel(); + } + + //-------------------------------------------------------------------- + PTableRenderer UnoControlTableModel::getRenderer() const + { + return m_pImpl->pRenderer; + } + + //-------------------------------------------------------------------- + PTableInputHandler UnoControlTableModel::getInputHandler() const + { + return m_pImpl->pInputHandler; + } + + //-------------------------------------------------------------------- + TableMetrics UnoControlTableModel::getRowHeight() const + { + return m_pImpl->nRowHeight; + } + //-------------------------------------------------------------------- + void UnoControlTableModel::setRowHeight(TableMetrics _nRowHeight) + { + m_pImpl->nRowHeight = _nRowHeight; + } + + //-------------------------------------------------------------------- + TableMetrics UnoControlTableModel::getColumnHeaderHeight() const + { + DBG_ASSERT( hasColumnHeaders(), "DefaultTableModel::getColumnHeaderHeight: invalid call!" ); + return m_pImpl->nColumnHeaderHeight; + } + + //-------------------------------------------------------------------- + TableMetrics UnoControlTableModel::getRowHeaderWidth() const + { + DBG_ASSERT( hasRowHeaders(), "DefaultTableModel::getRowHeaderWidth: invalid call!" ); + return m_pImpl->nRowHeaderWidth; + } + + //-------------------------------------------------------------------- + void UnoControlTableModel::SetTitleHeight( TableMetrics _nHeight ) + { + DBG_ASSERT( _nHeight > 0, "DefaultTableModel::SetTitleHeight: invalid height value!" ); + m_pImpl->nColumnHeaderHeight = _nHeight; + // TODO: notification + } + + //-------------------------------------------------------------------- + void UnoControlTableModel::SetHandleWidth( TableMetrics _nWidth ) + { + DBG_ASSERT( _nWidth > 0, "DefaultTableModel::SetHandleWidth: invalid width value!" ); + m_pImpl->nRowHeaderWidth = _nWidth; + // TODO: notification + } + + //-------------------------------------------------------------------- + ScrollbarVisibility UnoControlTableModel::getVerticalScrollbarVisibility(int overAllHeight, int actHeight) const + { + if(overAllHeight>=actHeight && !m_bVScroll) + return ScrollbarShowNever; + else + return ScrollbarShowAlways; + } + + //-------------------------------------------------------------------- + ScrollbarVisibility UnoControlTableModel::getHorizontalScrollbarVisibility(int overAllWidth, int actWidth) const + { + if(overAllWidth>=actWidth && !m_bHScroll) + return ScrollbarShowNever; + else + return ScrollbarShowAlways; + } + //-------------------------------------------------------------------- + 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() + { + return m_pImpl->aCellContent; + } + + //-------------------------------------------------------------------- + void UnoControlTableModel::setRowHeaderName(std::vector<rtl::OUString> cellColumnContent) + { + if(cellColumnContent.empty()) + { + unsigned int i = m_pImpl->aColumns.size(); + while(i!=0) + { + cellColumnContent.push_back(rtl::OUString::createFromAscii("")); + --i; + } + } + for(::std::vector<rtl::OUString>::iterator iter = cellColumnContent.begin(); iter!= cellColumnContent.end();++iter) + { + rtl::OUString s = *iter; + m_pImpl->aRowHeadersTitle.push_back(*iter); + } + } + + 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 new file mode 100644 index 000000000000..5da9cc871756 --- /dev/null +++ b/svtools/source/uno/unocontroltablemodel.hxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * 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: unocontroltablemodel.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 _UNOCONTROL_TABLEMODEL_HXX_ +#define _UNOCONTROL_TABLEMODEL_HXX_ + +#include <svtools/table/tablemodel.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; + + struct UnoControlTableModel_Impl; + + class UnoControlTableModel : public ITableModel, public ::cppu::ImplInheritanceHelper2< VCLXWindow, ::com::sun::star::awt::grid::XGridControl, + ::com::sun::star::awt::grid::XGridDataListener> + { + 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(); + ~UnoControlTableModel(); + + /// returns the current row height, in 1/100 millimeters + inline TableMetrics GetRowHeight() const { return getRowHeight(); } + /// sets a new row height. + void setRowHeight( TableMetrics _nHeight ); + + /// returns the height of the title row (containing the column headers) + inline TableMetrics GetTitleHeight() const { return getColumnHeaderHeight(); } + /// sets a new height for the title row (containing the column headers) + void SetTitleHeight( TableMetrics _nHeight ); + + /// returns the width of the handle column (containing the row headers) + inline TableMetrics GetHandleWidth() const { return getRowHeaderWidth(); } + /// sets a new width for the handle column (containing the row headers) + void SetHandleWidth( TableMetrics _nWidth ); + + /// sets the width of a column + inline void SetColumnWidth( ColPos _nColumn, TableMetrics _nWidth100thMM ); + /// retrieves the width of a column, in 1/100th millimeters + inline TableMetrics GetColumnWidth( ColPos _nColumn ); + + // TODO: setters and getters for ID, Name, Resizable, MinWidth, MaxWidth + + public: + // ITableModel overridables + virtual TableSize getColumnCount() const; + virtual TableSize getRowCount() const; + virtual void setColumnCount(TableSize _nColCount); + virtual void setRowCount(TableSize _nRowCount); + virtual bool hasColumnHeaders() const; + virtual bool hasRowHeaders() const; + virtual void setRowHeaders(bool _bRowHeaders); + virtual void setColumnHeaders(bool _bColumnHeaders); + virtual bool isCellEditable( ColPos col, RowPos row ) const; + virtual void addTableModelListener( const PTableModelListener& listener ); + virtual void removeTableModelListener( const PTableModelListener& listener ); + virtual PColumnModel getColumnModel( ColPos column ); + virtual PColumnModel getColumnModelByID( ColumnID id ); + virtual PTableRenderer getRenderer() const; + virtual PTableInputHandler getInputHandler() const; + virtual TableMetrics getRowHeight() const; + virtual TableMetrics getColumnHeaderHeight() const; + virtual TableMetrics getRowHeaderWidth() const; + 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 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); + }; + + inline void UnoControlTableModel::SetColumnWidth( ColPos _nColumn, TableMetrics _nWidth100thMM ) + { + getColumnModel( _nColumn )->setWidth( _nWidth100thMM ); + } + + inline TableMetrics UnoControlTableModel::GetColumnWidth( ColPos _nColumn ) + { + return getColumnModel( _nColumn )->getWidth(); + } + #endif // _UNOCONTROL_TABLEMODEL_HXX_ diff --git a/svtools/source/uno/unoiface.cxx b/svtools/source/uno/unoiface.cxx index 91a6de4c404d..e6922aa4f099 100644 --- a/svtools/source/uno/unoiface.cxx +++ b/svtools/source/uno/unoiface.cxx @@ -54,6 +54,9 @@ #include <svtools/svtreebx.hxx> #include "treecontrolpeer.hxx" +//#include "vclxgridcontrol.hxx" +#include "unocontroltablemodel.hxx" +#include <svtools/table/tablecontrol.hxx> namespace { @@ -83,8 +86,6 @@ SAL_DLLPUBLIC_EXPORT Window* CreateWindow( VCLXWindow** ppNewComp, const ::com:: if ( pParent ) { pWindow = new MultiLineEdit( pParent, nWinBits|WB_IGNORETAB); - static_cast< MultiLineEdit* >( pWindow )->DisableSelectionOnFocus(); - // #i89821# / 2008-12-17 / frank.schoenheit@sun.com *ppNewComp = new VCLXMultiLineEdit; } else @@ -167,6 +168,21 @@ SAL_DLLPUBLIC_EXPORT Window* CreateWindow( VCLXWindow** ppNewComp, const ::com:: return NULL; } } + else if ( aServiceName.EqualsIgnoreCaseAscii( "Grid" ) ) + { + if ( pParent ) + { + ::svt::table::TableControl* m_pTable = new ::svt::table::TableControl(pParent, nWinBits); + UnoControlTableModel* pModel = new UnoControlTableModel(); + *ppNewComp = pModel; + pWindow = m_pTable; + } + else + { + *ppNewComp = NULL; + return NULL; + } + } return pWindow; } diff --git a/svtools/uno/makefile.mk b/svtools/uno/makefile.mk index b572242f1d85..8f61c7100508 100644 --- a/svtools/uno/makefile.mk +++ b/svtools/uno/makefile.mk @@ -60,11 +60,13 @@ SHL1LIBS= \ SHL1STDLIBS=\ $(SVTOOLLIB) \ + $(TKLIB) \ $(VCLLIB) \ $(SVLLIB) \ $(UNOTOOLSLIB) \ $(TOOLSLIB) \ $(COMPHELPERLIB) \ + $(VOSLIB) \ $(CPPUHELPERLIB) \ $(CPPULIB) \ $(SALLIB) diff --git a/svtools/util/makefile.mk b/svtools/util/makefile.mk index d40195609115..80596d23e866 100644 --- a/svtools/util/makefile.mk +++ b/svtools/util/makefile.mk @@ -84,6 +84,7 @@ LIB7FILES= \ $(SLB)$/svhtml.lib \ $(SLB)$/svrtf.lib \ $(SLB)$/heavyconfig.lib \ + $(SLB)$/table.lib \ $(SLB)$/java.lib LIB8TARGET= $(SLB)$/svl.lib |