xref: /AOO41X/main/svtools/source/table/gridtablerenderer.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
1*5900e8ecSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*5900e8ecSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*5900e8ecSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*5900e8ecSAndrew Rist  * distributed with this work for additional information
6*5900e8ecSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*5900e8ecSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*5900e8ecSAndrew Rist  * "License"); you may not use this file except in compliance
9*5900e8ecSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*5900e8ecSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*5900e8ecSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*5900e8ecSAndrew Rist  * software distributed under the License is distributed on an
15*5900e8ecSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*5900e8ecSAndrew Rist  * KIND, either express or implied.  See the License for the
17*5900e8ecSAndrew Rist  * specific language governing permissions and limitations
18*5900e8ecSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*5900e8ecSAndrew Rist  *************************************************************/
21*5900e8ecSAndrew Rist 
22*5900e8ecSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svtools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "cellvalueconversion.hxx"
28cdf0e10cSrcweir #include "svtools/table/gridtablerenderer.hxx"
29cdf0e10cSrcweir #include "svtools/colorcfg.hxx"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir /** === begin UNO includes === **/
32cdf0e10cSrcweir #include <com/sun/star/graphic/XGraphic.hpp>
33cdf0e10cSrcweir /** === end UNO includes === **/
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <comphelper/componentcontext.hxx>
36cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
37cdf0e10cSrcweir #include <tools/debug.hxx>
38cdf0e10cSrcweir #include <tools/diagnose_ex.h>
39cdf0e10cSrcweir #include <vcl/window.hxx>
40cdf0e10cSrcweir #include <vcl/image.hxx>
41cdf0e10cSrcweir #include <vcl/virdev.hxx>
42cdf0e10cSrcweir #include <vcl/decoview.hxx>
43cdf0e10cSrcweir 
44cdf0e10cSrcweir //......................................................................................................................
45cdf0e10cSrcweir namespace svt { namespace table
46cdf0e10cSrcweir {
47cdf0e10cSrcweir //......................................................................................................................
48cdf0e10cSrcweir 
49cdf0e10cSrcweir     /** === begin UNO using === **/
50cdf0e10cSrcweir     using ::com::sun::star::uno::Any;
51cdf0e10cSrcweir     using ::com::sun::star::uno::Reference;
52cdf0e10cSrcweir     using ::com::sun::star::uno::UNO_QUERY;
53cdf0e10cSrcweir     using ::com::sun::star::uno::XInterface;
54cdf0e10cSrcweir     using ::com::sun::star::uno::TypeClass_INTERFACE;
55cdf0e10cSrcweir     using ::com::sun::star::graphic::XGraphic;
56cdf0e10cSrcweir     using ::com::sun::star::style::HorizontalAlignment;
57cdf0e10cSrcweir     using ::com::sun::star::style::HorizontalAlignment_LEFT;
58cdf0e10cSrcweir     using ::com::sun::star::style::HorizontalAlignment_CENTER;
59cdf0e10cSrcweir     using ::com::sun::star::style::HorizontalAlignment_RIGHT;
60cdf0e10cSrcweir     using ::com::sun::star::style::VerticalAlignment;
61cdf0e10cSrcweir     using ::com::sun::star::style::VerticalAlignment_TOP;
62cdf0e10cSrcweir     using ::com::sun::star::style::VerticalAlignment_MIDDLE;
63cdf0e10cSrcweir     using ::com::sun::star::style::VerticalAlignment_BOTTOM;
64cdf0e10cSrcweir     /** === end UNO using === **/
65cdf0e10cSrcweir 
66cdf0e10cSrcweir     //==================================================================================================================
67cdf0e10cSrcweir 	//= CachedSortIndicator
68cdf0e10cSrcweir     //==================================================================================================================
69cdf0e10cSrcweir     class CachedSortIndicator
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir     public:
72cdf0e10cSrcweir         CachedSortIndicator()
73cdf0e10cSrcweir             :m_lastHeaderHeight( 0 )
74cdf0e10cSrcweir             ,m_lastArrowColor( COL_TRANSPARENT )
75cdf0e10cSrcweir         {
76cdf0e10cSrcweir         }
77cdf0e10cSrcweir 
78cdf0e10cSrcweir         BitmapEx const & getBitmapFor( OutputDevice const & i_device, long const i_headerHeight, StyleSettings const & i_style, bool const i_sortAscending );
79cdf0e10cSrcweir 
80cdf0e10cSrcweir     private:
81cdf0e10cSrcweir         long        m_lastHeaderHeight;
82cdf0e10cSrcweir         Color       m_lastArrowColor;
83cdf0e10cSrcweir         BitmapEx    m_sortAscending;
84cdf0e10cSrcweir         BitmapEx    m_sortDescending;
85cdf0e10cSrcweir     };
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
88cdf0e10cSrcweir     BitmapEx const & CachedSortIndicator::getBitmapFor( OutputDevice const & i_device, long const i_headerHeight,
89cdf0e10cSrcweir         StyleSettings const & i_style, bool const i_sortAscending )
90cdf0e10cSrcweir     {
91cdf0e10cSrcweir         BitmapEx & rBitmap( i_sortAscending ? m_sortAscending : m_sortDescending );
92cdf0e10cSrcweir         if ( !rBitmap || ( i_headerHeight != m_lastHeaderHeight ) || ( i_style.GetActiveColor() != m_lastArrowColor ) )
93cdf0e10cSrcweir         {
94cdf0e10cSrcweir             long const nSortIndicatorWidth = 2 * i_headerHeight / 3;
95cdf0e10cSrcweir             long const nSortIndicatorHeight = 2 * nSortIndicatorWidth / 3;
96cdf0e10cSrcweir 
97cdf0e10cSrcweir             Point const aBitmapPos( 0, 0 );
98cdf0e10cSrcweir             Size const aBitmapSize( nSortIndicatorWidth, nSortIndicatorHeight );
99cdf0e10cSrcweir             VirtualDevice aDevice( i_device, 0, 0 );
100cdf0e10cSrcweir             aDevice.SetOutputSizePixel( aBitmapSize );
101cdf0e10cSrcweir 
102cdf0e10cSrcweir             DecorationView aDecoView( &aDevice );
103cdf0e10cSrcweir             aDecoView.DrawSymbol(
104cdf0e10cSrcweir                 Rectangle( aBitmapPos, aBitmapSize ),
105cdf0e10cSrcweir                 i_sortAscending ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN,
106cdf0e10cSrcweir                 i_style.GetActiveColor()
107cdf0e10cSrcweir             );
108cdf0e10cSrcweir 
109cdf0e10cSrcweir             rBitmap = aDevice.GetBitmapEx( aBitmapPos, aBitmapSize );
110cdf0e10cSrcweir             m_lastHeaderHeight = i_headerHeight;
111cdf0e10cSrcweir             m_lastArrowColor = i_style.GetActiveColor();
112cdf0e10cSrcweir         }
113cdf0e10cSrcweir         return rBitmap;
114cdf0e10cSrcweir     }
115cdf0e10cSrcweir 
116cdf0e10cSrcweir     //==================================================================================================================
117cdf0e10cSrcweir 	//= GridTableRenderer_Impl
118cdf0e10cSrcweir     //==================================================================================================================
119cdf0e10cSrcweir     struct GridTableRenderer_Impl
120cdf0e10cSrcweir     {
121cdf0e10cSrcweir         ITableModel&        rModel;
122cdf0e10cSrcweir         RowPos              nCurrentRow;
123cdf0e10cSrcweir         bool                bUseGridLines;
124cdf0e10cSrcweir         CachedSortIndicator aSortIndicator;
125cdf0e10cSrcweir         CellValueConversion aStringConverter;
126cdf0e10cSrcweir 
127cdf0e10cSrcweir         GridTableRenderer_Impl( ITableModel& _rModel )
128cdf0e10cSrcweir             :rModel( _rModel )
129cdf0e10cSrcweir             ,nCurrentRow( ROW_INVALID )
130cdf0e10cSrcweir             ,bUseGridLines( true )
131cdf0e10cSrcweir             ,aSortIndicator( )
132cdf0e10cSrcweir             ,aStringConverter( ::comphelper::ComponentContext( ::comphelper::getProcessServiceFactory() ) )
133cdf0e10cSrcweir         {
134cdf0e10cSrcweir         }
135cdf0e10cSrcweir     };
136cdf0e10cSrcweir 
137cdf0e10cSrcweir     //==================================================================================================================
138cdf0e10cSrcweir 	//= helper
139cdf0e10cSrcweir     //==================================================================================================================
140cdf0e10cSrcweir     namespace
141cdf0e10cSrcweir     {
142cdf0e10cSrcweir         static Rectangle lcl_getContentArea( GridTableRenderer_Impl const & i_impl, Rectangle const & i_cellArea )
143cdf0e10cSrcweir         {
144cdf0e10cSrcweir             Rectangle aContentArea( i_cellArea );
145cdf0e10cSrcweir             if ( i_impl.bUseGridLines )
146cdf0e10cSrcweir             {
147cdf0e10cSrcweir                 --aContentArea.Right();
148cdf0e10cSrcweir                 --aContentArea.Bottom();
149cdf0e10cSrcweir             }
150cdf0e10cSrcweir             return aContentArea;
151cdf0e10cSrcweir         }
152cdf0e10cSrcweir         static Rectangle lcl_getTextRenderingArea( Rectangle const & i_contentArea )
153cdf0e10cSrcweir         {
154cdf0e10cSrcweir             Rectangle aTextArea( i_contentArea );
155cdf0e10cSrcweir             aTextArea.Left() += 2; aTextArea.Right() -= 2;
156cdf0e10cSrcweir             ++aTextArea.Top(); --aTextArea.Bottom();
157cdf0e10cSrcweir             return aTextArea;
158cdf0e10cSrcweir         }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir         static sal_uLong lcl_getAlignmentTextDrawFlags( GridTableRenderer_Impl const & i_impl, ColPos const i_columnPos )
161cdf0e10cSrcweir         {
162cdf0e10cSrcweir             sal_uLong nVertFlag = TEXT_DRAW_TOP;
163cdf0e10cSrcweir             VerticalAlignment const eVertAlign = i_impl.rModel.getVerticalAlign();
164cdf0e10cSrcweir             switch ( eVertAlign )
165cdf0e10cSrcweir             {
166cdf0e10cSrcweir             case VerticalAlignment_MIDDLE:  nVertFlag = TEXT_DRAW_VCENTER;  break;
167cdf0e10cSrcweir             case VerticalAlignment_BOTTOM:  nVertFlag = TEXT_DRAW_BOTTOM;   break;
168cdf0e10cSrcweir             default:
169cdf0e10cSrcweir                 break;
170cdf0e10cSrcweir             }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir             sal_uLong nHorzFlag = TEXT_DRAW_LEFT;
173cdf0e10cSrcweir             HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnCount() > 0
174cdf0e10cSrcweir                                                 ?  i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign()
175cdf0e10cSrcweir                                                 :  HorizontalAlignment_CENTER;
176cdf0e10cSrcweir             switch ( eHorzAlign )
177cdf0e10cSrcweir             {
178cdf0e10cSrcweir             case HorizontalAlignment_CENTER:    nHorzFlag = TEXT_DRAW_CENTER;   break;
179cdf0e10cSrcweir             case HorizontalAlignment_RIGHT:     nHorzFlag = TEXT_DRAW_RIGHT;    break;
180cdf0e10cSrcweir             default:
181cdf0e10cSrcweir                 break;
182cdf0e10cSrcweir             }
183cdf0e10cSrcweir 
184cdf0e10cSrcweir             return nVertFlag | nHorzFlag;
185cdf0e10cSrcweir         }
186cdf0e10cSrcweir 
187cdf0e10cSrcweir     }
188cdf0e10cSrcweir 
189cdf0e10cSrcweir     //==================================================================================================================
190cdf0e10cSrcweir 	//= GridTableRenderer
191cdf0e10cSrcweir     //==================================================================================================================
192cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
193cdf0e10cSrcweir     GridTableRenderer::GridTableRenderer( ITableModel& _rModel )
194cdf0e10cSrcweir         :m_pImpl( new GridTableRenderer_Impl( _rModel ) )
195cdf0e10cSrcweir     {
196cdf0e10cSrcweir     }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
199cdf0e10cSrcweir     GridTableRenderer::~GridTableRenderer()
200cdf0e10cSrcweir     {
201cdf0e10cSrcweir     }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
204cdf0e10cSrcweir     RowPos GridTableRenderer::getCurrentRow() const
205cdf0e10cSrcweir     {
206cdf0e10cSrcweir         return m_pImpl->nCurrentRow;
207cdf0e10cSrcweir     }
208cdf0e10cSrcweir 
209cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
210cdf0e10cSrcweir     bool GridTableRenderer::useGridLines() const
211cdf0e10cSrcweir     {
212cdf0e10cSrcweir         return m_pImpl->bUseGridLines;
213cdf0e10cSrcweir     }
214cdf0e10cSrcweir 
215cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
216cdf0e10cSrcweir     void GridTableRenderer::useGridLines( bool const i_use )
217cdf0e10cSrcweir     {
218cdf0e10cSrcweir         m_pImpl->bUseGridLines = i_use;
219cdf0e10cSrcweir     }
220cdf0e10cSrcweir 
221cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
222cdf0e10cSrcweir     namespace
223cdf0e10cSrcweir     {
224cdf0e10cSrcweir         Color lcl_getEffectiveColor(
225cdf0e10cSrcweir             ::boost::optional< ::Color > const & i_modelColor,
226cdf0e10cSrcweir             StyleSettings const & i_styleSettings,
227cdf0e10cSrcweir             ::Color const & ( StyleSettings::*i_getDefaultColor ) () const
228cdf0e10cSrcweir         )
229cdf0e10cSrcweir         {
230cdf0e10cSrcweir             if ( !!i_modelColor )
231cdf0e10cSrcweir                 return *i_modelColor;
232cdf0e10cSrcweir             return ( i_styleSettings.*i_getDefaultColor )();
233cdf0e10cSrcweir         }
234cdf0e10cSrcweir     }
235cdf0e10cSrcweir 
236cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
237cdf0e10cSrcweir     void GridTableRenderer::PaintHeaderArea(
238cdf0e10cSrcweir         OutputDevice& _rDevice, const Rectangle& _rArea, bool _bIsColHeaderArea, bool _bIsRowHeaderArea,
239cdf0e10cSrcweir         const StyleSettings& _rStyle )
240cdf0e10cSrcweir 	{
241cdf0e10cSrcweir 		OSL_PRECOND( _bIsColHeaderArea || _bIsRowHeaderArea,
242cdf0e10cSrcweir             "GridTableRenderer::PaintHeaderArea: invalid area flags!" );
243cdf0e10cSrcweir 
244cdf0e10cSrcweir         _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
245cdf0e10cSrcweir 
246cdf0e10cSrcweir         Color const background = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderBackgroundColor(), _rStyle, &StyleSettings::GetDialogColor );
247cdf0e10cSrcweir 		_rDevice.SetFillColor( background );
248cdf0e10cSrcweir 
249cdf0e10cSrcweir         _rDevice.SetLineColor();
250cdf0e10cSrcweir         _rDevice.DrawRect( _rArea );
251cdf0e10cSrcweir 
252cdf0e10cSrcweir         // delimiter lines at bottom/right
253cdf0e10cSrcweir         ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
254cdf0e10cSrcweir         ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
255cdf0e10cSrcweir         _rDevice.SetLineColor( lineColor );
256cdf0e10cSrcweir         _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
257cdf0e10cSrcweir         _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
258cdf0e10cSrcweir 
259cdf0e10cSrcweir         _rDevice.Pop();
260cdf0e10cSrcweir 		(void)_bIsColHeaderArea;
261cdf0e10cSrcweir 		(void)_bIsRowHeaderArea;
262cdf0e10cSrcweir     }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
265cdf0e10cSrcweir     void GridTableRenderer::PaintColumnHeader( ColPos _nCol, bool _bActive, bool _bSelected,
266cdf0e10cSrcweir         OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle )
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         _rDevice.Push( PUSH_LINECOLOR);
269cdf0e10cSrcweir 
270cdf0e10cSrcweir         String sHeaderText;
271cdf0e10cSrcweir         PColumnModel const pColumn = m_pImpl->rModel.getColumnModel( _nCol );
272cdf0e10cSrcweir         DBG_ASSERT( !!pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" );
273cdf0e10cSrcweir         if ( !!pColumn )
274cdf0e10cSrcweir             sHeaderText = pColumn->getName();
275cdf0e10cSrcweir 
276cdf0e10cSrcweir         ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
277cdf0e10cSrcweir         _rDevice.SetTextColor( textColor );
278cdf0e10cSrcweir 
279cdf0e10cSrcweir 		Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) );
280cdf0e10cSrcweir         sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | TEXT_DRAW_CLIP;
281cdf0e10cSrcweir         _rDevice.DrawText( aTextRect, sHeaderText, nDrawTextFlags );
282cdf0e10cSrcweir 
283cdf0e10cSrcweir         ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() );
284cdf0e10cSrcweir         ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
285cdf0e10cSrcweir 		_rDevice.SetLineColor( lineColor );
286cdf0e10cSrcweir 		_rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight());
287cdf0e10cSrcweir 		_rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
288cdf0e10cSrcweir 
289cdf0e10cSrcweir         // draw sort indicator if the model data is sorted by the given column
290cdf0e10cSrcweir         ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter();
291cdf0e10cSrcweir         ColumnSort aCurrentSortOrder;
292cdf0e10cSrcweir         if ( pSortAdapter != NULL )
293cdf0e10cSrcweir             aCurrentSortOrder = pSortAdapter->getCurrentSortOrder();
294cdf0e10cSrcweir         if ( aCurrentSortOrder.nColumnPos == _nCol )
295cdf0e10cSrcweir         {
296cdf0e10cSrcweir             long const nHeaderHeight( _rArea.GetHeight() );
297cdf0e10cSrcweir             BitmapEx const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor( _rDevice, nHeaderHeight, _rStyle,
298cdf0e10cSrcweir                 aCurrentSortOrder.eSortDirection == ColumnSortAscending );
299cdf0e10cSrcweir             Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() );
300cdf0e10cSrcweir             long const nSortIndicatorPaddingX = 2;
301cdf0e10cSrcweir             long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2;
302cdf0e10cSrcweir 
303cdf0e10cSrcweir             if ( ( nDrawTextFlags & TEXT_DRAW_RIGHT ) != 0 )
304cdf0e10cSrcweir             {
305cdf0e10cSrcweir                 // text is right aligned => draw the sort indicator at the left hand side
306cdf0e10cSrcweir                 _rDevice.DrawBitmapEx(
307cdf0e10cSrcweir                     Point( _rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY ),
308cdf0e10cSrcweir                     aIndicatorBitmap
309cdf0e10cSrcweir                 );
310cdf0e10cSrcweir             }
311cdf0e10cSrcweir             else
312cdf0e10cSrcweir             {
313cdf0e10cSrcweir                 // text is left-aligned or centered => draw the sort indicator at the right hand side
314cdf0e10cSrcweir                 _rDevice.DrawBitmapEx(
315cdf0e10cSrcweir                     Point( _rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY ),
316cdf0e10cSrcweir                     aIndicatorBitmap
317cdf0e10cSrcweir                 );
318cdf0e10cSrcweir             }
319cdf0e10cSrcweir         }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir         _rDevice.Pop();
322cdf0e10cSrcweir 
323cdf0e10cSrcweir         (void)_bActive;
324cdf0e10cSrcweir         // no special painting for the active column at the moment
325cdf0e10cSrcweir 
326cdf0e10cSrcweir         (void)_bSelected;
327cdf0e10cSrcweir         // selection for column header not yet implemented
328cdf0e10cSrcweir     }
329cdf0e10cSrcweir 
330cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
331cdf0e10cSrcweir     void GridTableRenderer::PrepareRow( RowPos _nRow, bool i_hasControlFocus, bool _bSelected,
332cdf0e10cSrcweir         OutputDevice& _rDevice, const Rectangle& _rRowArea, const StyleSettings& _rStyle )
333cdf0e10cSrcweir     {
334cdf0e10cSrcweir         // remember the row for subsequent calls to the other ->ITableRenderer methods
335cdf0e10cSrcweir         m_pImpl->nCurrentRow = _nRow;
336cdf0e10cSrcweir 
337cdf0e10cSrcweir         _rDevice.Push( PUSH_FILLCOLOR | PUSH_LINECOLOR);
338cdf0e10cSrcweir 
339cdf0e10cSrcweir         ::Color backgroundColor = _rStyle.GetFieldColor();
340cdf0e10cSrcweir 
341cdf0e10cSrcweir         ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() );
342cdf0e10cSrcweir         ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
343cdf0e10cSrcweir 
344cdf0e10cSrcweir         ::Color const activeSelectionBackColor =
345cdf0e10cSrcweir             lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor );
346cdf0e10cSrcweir 		if ( _bSelected )
347cdf0e10cSrcweir 		{
348cdf0e10cSrcweir             // selected rows use the background color from the style
349cdf0e10cSrcweir             backgroundColor = i_hasControlFocus
350cdf0e10cSrcweir                 ?   activeSelectionBackColor
351cdf0e10cSrcweir                 :   lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor );
352cdf0e10cSrcweir             if ( !aLineColor )
353cdf0e10cSrcweir                 lineColor = backgroundColor;
354cdf0e10cSrcweir 		}
355cdf0e10cSrcweir         else
356cdf0e10cSrcweir         {
357cdf0e10cSrcweir             ::boost::optional< ::std::vector< ::Color > > aRowColors = m_pImpl->rModel.getRowBackgroundColors();
358cdf0e10cSrcweir             if ( !aRowColors )
359cdf0e10cSrcweir             {
360cdf0e10cSrcweir                 // use alternating default colors
361cdf0e10cSrcweir                 Color const fieldColor = _rStyle.GetFieldColor();
362cdf0e10cSrcweir                 if ( _rStyle.GetHighContrastMode() || ( ( m_pImpl->nCurrentRow % 2 ) == 0 ) )
363cdf0e10cSrcweir                 {
364cdf0e10cSrcweir                     backgroundColor = fieldColor;
365cdf0e10cSrcweir                 }
366cdf0e10cSrcweir                 else
367cdf0e10cSrcweir                 {
368cdf0e10cSrcweir                     Color hilightColor = activeSelectionBackColor;
369cdf0e10cSrcweir                     hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() );
370cdf0e10cSrcweir                     hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() );
371cdf0e10cSrcweir                     hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() );
372cdf0e10cSrcweir                     backgroundColor = hilightColor;
373cdf0e10cSrcweir                 }
374cdf0e10cSrcweir             }
375cdf0e10cSrcweir             else
376cdf0e10cSrcweir             {
377cdf0e10cSrcweir                 if ( aRowColors->empty() )
378cdf0e10cSrcweir                 {
379cdf0e10cSrcweir                     // all colors have the same background color
380cdf0e10cSrcweir                     backgroundColor = _rStyle.GetFieldColor();
381cdf0e10cSrcweir                 }
382cdf0e10cSrcweir                 else
383cdf0e10cSrcweir                 {
384cdf0e10cSrcweir                     backgroundColor = aRowColors->at( m_pImpl->nCurrentRow % aRowColors->size() );
385cdf0e10cSrcweir                 }
386cdf0e10cSrcweir             }
387cdf0e10cSrcweir         }
388cdf0e10cSrcweir 
389cdf0e10cSrcweir         //m_pImpl->bUseGridLines ? _rDevice.SetLineColor( lineColor ) : _rDevice.SetLineColor();
390cdf0e10cSrcweir         _rDevice.SetLineColor();
391cdf0e10cSrcweir         _rDevice.SetFillColor( backgroundColor );
392cdf0e10cSrcweir         _rDevice.DrawRect( _rRowArea );
393cdf0e10cSrcweir 
394cdf0e10cSrcweir         _rDevice.Pop();
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
398cdf0e10cSrcweir     void GridTableRenderer::PaintRowHeader( bool i_hasControlFocus, bool _bSelected, OutputDevice& _rDevice, const Rectangle& _rArea,
399cdf0e10cSrcweir 		const StyleSettings& _rStyle )
400cdf0e10cSrcweir     {
401cdf0e10cSrcweir         _rDevice.Push( PUSH_LINECOLOR | PUSH_TEXTCOLOR );
402cdf0e10cSrcweir 
403cdf0e10cSrcweir         ::boost::optional< ::Color > const aLineColor( m_pImpl->rModel.getLineColor() );
404cdf0e10cSrcweir         ::Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
405cdf0e10cSrcweir         _rDevice.SetLineColor( lineColor );
406cdf0e10cSrcweir         _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
407cdf0e10cSrcweir 
408cdf0e10cSrcweir         Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) );
409cdf0e10cSrcweir         ::rtl::OUString const rowTitle( m_pImpl->aStringConverter.convertToString( rowHeading ) );
410cdf0e10cSrcweir         if ( rowTitle.getLength() )
411cdf0e10cSrcweir         {
412cdf0e10cSrcweir             ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getHeaderTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
413cdf0e10cSrcweir             _rDevice.SetTextColor( textColor );
414cdf0e10cSrcweir 
415cdf0e10cSrcweir 		    Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) );
416cdf0e10cSrcweir             sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, 0 ) | TEXT_DRAW_CLIP;
417cdf0e10cSrcweir                 // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitray ..
418cdf0e10cSrcweir             _rDevice.DrawText( aTextRect, rowTitle, nDrawTextFlags );
419cdf0e10cSrcweir         }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir         (void)i_hasControlFocus;
422cdf0e10cSrcweir         (void)_bSelected;
423cdf0e10cSrcweir         _rDevice.Pop();
424cdf0e10cSrcweir     }
425cdf0e10cSrcweir 
426cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
427cdf0e10cSrcweir     struct GridTableRenderer::CellRenderContext
428cdf0e10cSrcweir     {
429cdf0e10cSrcweir         OutputDevice&           rDevice;
430cdf0e10cSrcweir         Rectangle const         aContentArea;
431cdf0e10cSrcweir         StyleSettings const &   rStyle;
432cdf0e10cSrcweir         ColPos const            nColumn;
433cdf0e10cSrcweir         bool const              bSelected;
434cdf0e10cSrcweir         bool const              bHasControlFocus;
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         CellRenderContext( OutputDevice& i_device, Rectangle const & i_contentArea,
437cdf0e10cSrcweir             StyleSettings const & i_style, ColPos const i_column, bool const i_selected, bool const i_hasControlFocus )
438cdf0e10cSrcweir             :rDevice( i_device )
439cdf0e10cSrcweir             ,aContentArea( i_contentArea )
440cdf0e10cSrcweir             ,rStyle( i_style )
441cdf0e10cSrcweir             ,nColumn( i_column )
442cdf0e10cSrcweir             ,bSelected( i_selected )
443cdf0e10cSrcweir             ,bHasControlFocus( i_hasControlFocus )
444cdf0e10cSrcweir         {
445cdf0e10cSrcweir         }
446cdf0e10cSrcweir     };
447cdf0e10cSrcweir 
448cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
449cdf0e10cSrcweir     void GridTableRenderer::PaintCell( ColPos const i_column, bool _bSelected, bool i_hasControlFocus,
450cdf0e10cSrcweir 		OutputDevice& _rDevice, const Rectangle& _rArea, const StyleSettings& _rStyle )
451cdf0e10cSrcweir     {
452cdf0e10cSrcweir         _rDevice.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
453cdf0e10cSrcweir 
454cdf0e10cSrcweir         Rectangle const aContentArea( lcl_getContentArea( *m_pImpl, _rArea ) );
455cdf0e10cSrcweir         CellRenderContext const aRenderContext( _rDevice, aContentArea, _rStyle, i_column, _bSelected, i_hasControlFocus );
456cdf0e10cSrcweir         impl_paintCellContent( aRenderContext );
457cdf0e10cSrcweir 
458cdf0e10cSrcweir         if ( m_pImpl->bUseGridLines )
459cdf0e10cSrcweir         {
460cdf0e10cSrcweir             ::boost::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
461cdf0e10cSrcweir             ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
462cdf0e10cSrcweir 
463cdf0e10cSrcweir 		    if ( _bSelected && !aLineColor )
464cdf0e10cSrcweir 		    {
465cdf0e10cSrcweir                 // if no line color is specified by the model, use the usual selection color for lines in selected cells
466cdf0e10cSrcweir                 lineColor = i_hasControlFocus
467cdf0e10cSrcweir                     ?   lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor )
468cdf0e10cSrcweir                     :   lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor );
469cdf0e10cSrcweir 		    }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir             _rDevice.SetLineColor( lineColor );
472cdf0e10cSrcweir 		    _rDevice.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
473cdf0e10cSrcweir 		    _rDevice.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
474cdf0e10cSrcweir         }
475cdf0e10cSrcweir 
476cdf0e10cSrcweir 		_rDevice.Pop();
477cdf0e10cSrcweir     }
478cdf0e10cSrcweir 
479cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
480cdf0e10cSrcweir     void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image )
481cdf0e10cSrcweir     {
482cdf0e10cSrcweir         Point imagePos( Point( i_context.aContentArea.Left(), i_context.aContentArea.Top() ) );
483cdf0e10cSrcweir         Size imageSize = i_image.GetSizePixel();
484cdf0e10cSrcweir         if ( i_context.aContentArea.GetWidth() > imageSize.Width() )
485cdf0e10cSrcweir         {
486cdf0e10cSrcweir             const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign();
487cdf0e10cSrcweir             switch ( eHorzAlign )
488cdf0e10cSrcweir             {
489cdf0e10cSrcweir             case HorizontalAlignment_CENTER:
490cdf0e10cSrcweir                 imagePos.X() += ( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2;
491cdf0e10cSrcweir                 break;
492cdf0e10cSrcweir             case HorizontalAlignment_RIGHT:
493cdf0e10cSrcweir                 imagePos.X() = i_context.aContentArea.Right() - imageSize.Width();
494cdf0e10cSrcweir                 break;
495cdf0e10cSrcweir             default:
496cdf0e10cSrcweir                 break;
497cdf0e10cSrcweir             }
498cdf0e10cSrcweir 
499cdf0e10cSrcweir         }
500cdf0e10cSrcweir         else
501cdf0e10cSrcweir 	        imageSize.Width() = i_context.aContentArea.GetWidth();
502cdf0e10cSrcweir 
503cdf0e10cSrcweir         if ( i_context.aContentArea.GetHeight() > imageSize.Height() )
504cdf0e10cSrcweir         {
505cdf0e10cSrcweir             const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign();
506cdf0e10cSrcweir             switch ( eVertAlign )
507cdf0e10cSrcweir             {
508cdf0e10cSrcweir             case VerticalAlignment_MIDDLE:
509cdf0e10cSrcweir 		        imagePos.Y() += ( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2;
510cdf0e10cSrcweir                 break;
511cdf0e10cSrcweir             case VerticalAlignment_BOTTOM:
512cdf0e10cSrcweir 		        imagePos.Y() = i_context.aContentArea.Bottom() - imageSize.Height();
513cdf0e10cSrcweir                 break;
514cdf0e10cSrcweir             default:
515cdf0e10cSrcweir                 break;
516cdf0e10cSrcweir             }
517cdf0e10cSrcweir         }
518cdf0e10cSrcweir         else
519cdf0e10cSrcweir 	        imageSize.Height() = i_context.aContentArea.GetHeight() - 1;
520cdf0e10cSrcweir 
521cdf0e10cSrcweir         i_context.rDevice.DrawImage( imagePos, imageSize, i_image, 0 );
522cdf0e10cSrcweir     }
523cdf0e10cSrcweir 
524cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
525cdf0e10cSrcweir     void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context )
526cdf0e10cSrcweir     {
527cdf0e10cSrcweir         Any aCellContent;
528cdf0e10cSrcweir         m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent );
529cdf0e10cSrcweir 
530cdf0e10cSrcweir         if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE )
531cdf0e10cSrcweir         {
532cdf0e10cSrcweir             Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY );
533cdf0e10cSrcweir             if ( !xContentInterface.is() )
534cdf0e10cSrcweir                 // allowed. kind of.
535cdf0e10cSrcweir                 return;
536cdf0e10cSrcweir 
537cdf0e10cSrcweir             Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY );
538cdf0e10cSrcweir             ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." );
539cdf0e10cSrcweir 
540cdf0e10cSrcweir             const Image aImage( xGraphic );
541cdf0e10cSrcweir             impl_paintCellImage( i_context, aImage );
542cdf0e10cSrcweir             return;
543cdf0e10cSrcweir         }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir         const ::rtl::OUString sText( m_pImpl->aStringConverter.convertToString( aCellContent ) );
546cdf0e10cSrcweir         impl_paintCellText( i_context, sText );
547cdf0e10cSrcweir     }
548cdf0e10cSrcweir 
549cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
550cdf0e10cSrcweir     void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, ::rtl::OUString const & i_text )
551cdf0e10cSrcweir     {
552cdf0e10cSrcweir         if ( i_context.bSelected )
553cdf0e10cSrcweir         {
554cdf0e10cSrcweir             ::Color const textColor = i_context.bHasControlFocus
555cdf0e10cSrcweir                 ?   lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetHighlightTextColor )
556cdf0e10cSrcweir                 :   lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetDeactiveTextColor );
557cdf0e10cSrcweir             i_context.rDevice.SetTextColor( textColor );
558cdf0e10cSrcweir         }
559cdf0e10cSrcweir         else
560cdf0e10cSrcweir         {
561cdf0e10cSrcweir             ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor );
562cdf0e10cSrcweir             i_context.rDevice.SetTextColor( textColor );
563cdf0e10cSrcweir         }
564cdf0e10cSrcweir 
565cdf0e10cSrcweir         Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) );
566cdf0e10cSrcweir         sal_uLong const nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | TEXT_DRAW_CLIP;
567cdf0e10cSrcweir         i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags );
568cdf0e10cSrcweir     }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
571cdf0e10cSrcweir     void GridTableRenderer::ShowCellCursor( Window& _rView, const Rectangle& _rCursorRect)
572cdf0e10cSrcweir     {
573cdf0e10cSrcweir         _rView.ShowFocus( _rCursorRect );
574cdf0e10cSrcweir     }
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
577cdf0e10cSrcweir     void GridTableRenderer::HideCellCursor( Window& _rView, const Rectangle& _rCursorRect)
578cdf0e10cSrcweir     {
579cdf0e10cSrcweir 	    (void)_rCursorRect;
580cdf0e10cSrcweir         _rView.HideFocus();
581cdf0e10cSrcweir     }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
584cdf0e10cSrcweir     bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent, ColPos const i_colPos, RowPos const i_rowPos,
585cdf0e10cSrcweir         bool const i_active, bool const i_selected, OutputDevice& i_targetDevice, Rectangle const & i_targetArea ) const
586cdf0e10cSrcweir     {
587cdf0e10cSrcweir         if ( !i_cellContent.hasValue() )
588cdf0e10cSrcweir             return true;
589cdf0e10cSrcweir 
590cdf0e10cSrcweir         if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE )
591cdf0e10cSrcweir         {
592cdf0e10cSrcweir             Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY );
593cdf0e10cSrcweir             if ( !xContentInterface.is() )
594cdf0e10cSrcweir                 return true;
595cdf0e10cSrcweir 
596cdf0e10cSrcweir             Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY );
597cdf0e10cSrcweir             if ( xGraphic.is() )
598cdf0e10cSrcweir                 // for the moment, assume it fits. We can always scale it down during painting ...
599cdf0e10cSrcweir                 return true;
600cdf0e10cSrcweir 
601cdf0e10cSrcweir             OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." );
602cdf0e10cSrcweir             return true;
603cdf0e10cSrcweir         }
604cdf0e10cSrcweir 
605cdf0e10cSrcweir         ::rtl::OUString const sText( m_pImpl->aStringConverter.convertToString( i_cellContent ) );
606cdf0e10cSrcweir         if ( sText.getLength() == 0 )
607cdf0e10cSrcweir             return true;
608cdf0e10cSrcweir 
609cdf0e10cSrcweir         Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) );
610cdf0e10cSrcweir 
611cdf0e10cSrcweir         long const nTextHeight = i_targetDevice.GetTextHeight();
612cdf0e10cSrcweir         if ( nTextHeight > aTargetArea.GetHeight() )
613cdf0e10cSrcweir             return false;
614cdf0e10cSrcweir 
615cdf0e10cSrcweir         long const nTextWidth = i_targetDevice.GetTextWidth( sText );
616cdf0e10cSrcweir         if ( nTextWidth > aTargetArea.GetWidth() )
617cdf0e10cSrcweir             return false;
618cdf0e10cSrcweir 
619cdf0e10cSrcweir         OSL_UNUSED( i_active );
620cdf0e10cSrcweir         OSL_UNUSED( i_selected );
621cdf0e10cSrcweir         OSL_UNUSED( i_rowPos );
622cdf0e10cSrcweir         OSL_UNUSED( i_colPos );
623cdf0e10cSrcweir         return true;
624cdf0e10cSrcweir     }
625cdf0e10cSrcweir 
626cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
627cdf0e10cSrcweir     bool GridTableRenderer::GetFormattedCellString( Any const & i_cellValue, ColPos const i_colPos, RowPos const i_rowPos, ::rtl::OUString & o_cellString ) const
628cdf0e10cSrcweir     {
629cdf0e10cSrcweir         o_cellString = m_pImpl->aStringConverter.convertToString( i_cellValue );
630cdf0e10cSrcweir 
631cdf0e10cSrcweir         OSL_UNUSED( i_colPos );
632cdf0e10cSrcweir         OSL_UNUSED( i_rowPos );
633cdf0e10cSrcweir         return true;
634cdf0e10cSrcweir     }
635cdf0e10cSrcweir 
636cdf0e10cSrcweir //......................................................................................................................
637cdf0e10cSrcweir } } // namespace svt::table
638cdf0e10cSrcweir //......................................................................................................................
639cdf0e10cSrcweir 
640