1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataBrowser.cxx,v $
10 * $Revision: 1.9.8.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
34 // header for class SvNumberformat
36 #ifndef _ZFORLIST_DECLARE_TABLE
37 #define _ZFORLIST_DECLARE_TABLE
39 #include <svtools/zformat.hxx>
41 // header for SvNumberFormatter
42 #include <svtools/zforlist.hxx>
44 #include "DataBrowser.hxx"
45 #include "DataBrowserModel.hxx"
46 #include "Strings.hrc"
47 #include "ContainerHelper.hxx"
48 #include "DataSeriesHelper.hxx"
49 #include "DiagramHelper.hxx"
50 #include "ChartModelHelper.hxx"
51 #include "chartview/NumberFormatterWrapper.hxx"
52 #include "servicenames_charttypes.hxx"
54 #include "Bitmaps.hrc"
55 #include "Bitmaps_HC.hrc"
56 #include "HelpIds.hrc"
58 #include <vcl/fixed.hxx>
59 #include <vcl/image.hxx>
60 #include <vcl/msgbox.hxx>
61 #include <rtl/math.hxx>
63 #include <com/sun/star/util/XCloneable.hpp>
64 #include <com/sun/star/chart2/XChartDocument.hpp>
65 #include <com/sun/star/chart2/XChartType.hpp>
67 #include <com/sun/star/container/XIndexReplace.hpp>
72 #define SELECT_IMAGE(name,hc) Image( SchResId( hc ? name ## _HC : name ))
74 /* BROWSER_COLUMNSELECTION : single cells may be selected rather than only
76 BROWSER_(H|V)LINES : show horizontal or vertical grid-lines
78 BROWSER_AUTO_(H|V)SCROLL : scroll automated horizontally or vertically when
79 cursor is moved beyond the edge of the dialog
80 BROWSER_HIGHLIGHT_NONE : Do not mark the current row with selection color
84 #define BROWSER_STANDARD_FLAGS \
85 BROWSER_COLUMNSELECTION | \
86 BROWSER_HLINES | BROWSER_VLINES | \
87 BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL | \
88 BROWSER_HIGHLIGHT_NONE
90 // BROWSER_HIDECURSOR would prevent flickering in edit fields, but navigating
91 // with shift up/down, and entering non-editable cells would be problematic,
92 // e.g. the first cell, or when being in read-only mode
95 using namespace ::com::sun::star
;
96 using ::com::sun::star::uno::Sequence
;
97 using ::com::sun::star::uno::Reference
;
98 using ::rtl::OUString
;
100 using namespace ::svt
;
104 sal_Int32
lcl_getRowInData( long nRow
)
106 return static_cast< sal_Int32
>( nRow
);
109 sal_Int32
lcl_getColumnInData( USHORT nCol
)
111 return static_cast< sal_Int32
>( nCol
) - 1;
114 } // anonymous namespace
116 // --------------------------------------------------------------------------------
121 // ----------------------------------------
125 class SeriesHeaderEdit
: public Edit
128 SeriesHeaderEdit( Window
* pParent
);
129 virtual ~SeriesHeaderEdit();
130 virtual void MouseButtonDown( const MouseEvent
& rMEvt
);
132 void setStartColumn( sal_Int32 nStartColumn
);
133 sal_Int32
getStartColumn() const;
134 void SetShowWarningBox( bool bShowWarning
= true );
137 sal_Int32 m_nStartColumn
;
138 bool m_bShowWarningBox
;
141 SeriesHeaderEdit::SeriesHeaderEdit( Window
* pParent
) :
144 m_bShowWarningBox( false )
146 SeriesHeaderEdit::~SeriesHeaderEdit()
149 void SeriesHeaderEdit::setStartColumn( sal_Int32 nStartColumn
)
151 m_nStartColumn
= nStartColumn
;
154 sal_Int32
SeriesHeaderEdit::getStartColumn() const
156 return m_nStartColumn
;
159 void SeriesHeaderEdit::SetShowWarningBox( bool bShowWarning
)
161 m_bShowWarningBox
= bShowWarning
;
164 void SeriesHeaderEdit::MouseButtonDown( const MouseEvent
& rMEvt
)
166 Edit::MouseButtonDown( rMEvt
);
168 if( m_bShowWarningBox
)
169 WarningBox( this, WinBits( WB_OK
),
170 String( SchResId( STR_INVALID_NUMBER
))).Execute();
176 explicit SeriesHeader( Window
* pParent
);
178 void SetColor( const Color
& rCol
);
179 void SetPos( const Point
& rPos
);
180 void SetWidth( sal_Int32 nWidth
);
181 void SetChartType( const Reference
< chart2::XChartType
> & xChartType
,
183 bool bIsHighContrast
);
184 void SetSeriesName( const String
& rName
);
185 void SetRange( sal_Int32 nStartCol
, sal_Int32 nEndCol
);
187 void SetPixelPosX( sal_Int32 nPos
);
188 void SetPixelWidth( sal_Int32 nWidth
);
190 sal_Int32
GetStartColumn() const;
191 sal_Int32
GetEndColumn() const;
195 /** call this before destroying the class. This notifies the listeners to
196 changes of the edit field for the series name.
200 void SetGetFocusHdl( const Link
& rLink
);
202 void SetEditChangedHdl( const Link
& rLink
);
204 bool HasFocus() const;
207 ::boost::shared_ptr
< FixedImage
> m_spSymbol
;
208 ::boost::shared_ptr
< SeriesHeaderEdit
> m_spSeriesName
;
209 ::boost::shared_ptr
< FixedText
> m_spColorBar
;
210 OutputDevice
* m_pDevice
;
213 void notifyChanges();
214 DECL_LINK( SeriesNameChanged
, void * );
215 DECL_LINK( SeriesNameEdited
, void * );
217 /// @param bHC </TRUE> for hight-contrast image
218 static Image
GetChartTypeImage(
219 const Reference
< chart2::XChartType
> & xChartType
,
223 sal_Int32 m_nStartCol
, m_nEndCol
;
226 bool m_bSeriesNameChangePending
;
229 SeriesHeader::SeriesHeader( Window
* pParent
) :
230 m_spSymbol( new FixedImage( pParent
, WB_NOBORDER
)),
231 m_spSeriesName( new SeriesHeaderEdit( pParent
)),
232 m_spColorBar( new FixedText( pParent
, WB_NOBORDER
)),
233 m_pDevice( pParent
),
238 m_bSeriesNameChangePending( false )
240 m_spSeriesName
->EnableUpdateData( 4 * EDIT_UPDATEDATA_TIMEOUT
); // define is in vcl/edit.hxx
241 m_spSeriesName
->SetUpdateDataHdl( LINK( this, SeriesHeader
, SeriesNameChanged
));
242 m_spSeriesName
->SetModifyHdl( LINK( this, SeriesHeader
, SeriesNameEdited
));
243 m_spSeriesName
->SetSmartHelpId( SmartId( HID_SCH_DATA_SERIES_LABEL
));
247 void SeriesHeader::notifyChanges()
249 if( m_aChangeLink
.IsSet())
250 m_aChangeLink
.Call( m_spSeriesName
.get());
252 m_bSeriesNameChangePending
= false;
255 void SeriesHeader::applyChanges()
257 if( m_bSeriesNameChangePending
)
263 void SeriesHeader::SetColor( const Color
& rCol
)
265 m_spColorBar
->SetControlBackground( rCol
);
268 void SeriesHeader::SetPos( const Point
& rPos
)
273 sal_Int32 nHeight
= 10;
275 aPos
.setY( aPos
.getY() + 2 );
276 Size
aSize( nHeight
, nHeight
);
277 m_spSymbol
->SetPosPixel( m_pDevice
->LogicToPixel( aPos
, MAP_APPFONT
));
278 m_spSymbol
->SetSizePixel( m_pDevice
->LogicToPixel( aSize
, MAP_APPFONT
));
279 aPos
.setY( aPos
.getY() - 2 );
281 // series name edit field
282 aPos
.setX( aPos
.getX() + nHeight
+ 2 );
283 aSize
.setWidth( m_nWidth
- nHeight
- 2 );
285 aSize
.setHeight( nHeight
);
286 m_spSeriesName
->SetPosPixel( m_pDevice
->LogicToPixel( aPos
, MAP_APPFONT
));
287 m_spSeriesName
->SetSizePixel( m_pDevice
->LogicToPixel( aSize
, MAP_APPFONT
));
290 aPos
.setX( rPos
.getX() + 1 );
291 aPos
.setY( aPos
.getY() + nHeight
+ 2 );
293 aSize
.setWidth( m_nWidth
- 1 );
294 aSize
.setHeight( nHeight
);
295 m_spColorBar
->SetPosPixel( m_pDevice
->LogicToPixel( aPos
, MAP_APPFONT
));
296 m_spColorBar
->SetSizePixel( m_pDevice
->LogicToPixel( aSize
, MAP_APPFONT
));
299 void SeriesHeader::SetWidth( sal_Int32 nWidth
)
306 void SeriesHeader::SetPixelPosX( sal_Int32 nPos
)
308 Point
aPos( m_pDevice
->LogicToPixel( m_aPos
, MAP_APPFONT
));
310 SetPos( m_pDevice
->PixelToLogic( aPos
, MAP_APPFONT
));
313 void SeriesHeader::SetPixelWidth( sal_Int32 nWidth
)
315 SetWidth( m_pDevice
->PixelToLogic( Size( nWidth
, 0 ), MAP_APPFONT
).getWidth());
318 void SeriesHeader::SetChartType(
319 const Reference
< chart2::XChartType
> & xChartType
,
321 bool bIsHighContrast
)
323 m_spSymbol
->SetImage( GetChartTypeImage( xChartType
, bSwapXAndYAxis
, bIsHighContrast
));
326 void SeriesHeader::SetSeriesName( const String
& rName
)
328 m_spSeriesName
->SetText( rName
);
331 void SeriesHeader::SetRange( sal_Int32 nStartCol
, sal_Int32 nEndCol
)
333 m_nStartCol
= nStartCol
;
334 m_nEndCol
= (nEndCol
> nStartCol
) ? nEndCol
: nStartCol
;
335 m_spSeriesName
->setStartColumn( nStartCol
);
338 sal_Int32
SeriesHeader::GetStartColumn() const
343 sal_Int32
SeriesHeader::GetEndColumn() const
348 void SeriesHeader::Show()
351 m_spSeriesName
->Show();
352 m_spColorBar
->Show();
355 void SeriesHeader::SetEditChangedHdl( const Link
& rLink
)
357 m_aChangeLink
= rLink
;
360 IMPL_LINK( SeriesHeader
, SeriesNameChanged
, void * , EMPTYARG
)
366 IMPL_LINK( SeriesHeader
, SeriesNameEdited
, void * , EMPTYARG
)
368 m_bSeriesNameChangePending
= true;
372 void SeriesHeader::SetGetFocusHdl( const Link
& rLink
)
374 m_spSeriesName
->SetGetFocusHdl( rLink
);
377 bool SeriesHeader::HasFocus() const
379 return m_spSeriesName
->HasFocus();
383 Image
SeriesHeader::GetChartTypeImage(
384 const Reference
< chart2::XChartType
> & xChartType
,
389 if( !xChartType
.is())
391 OUString
aChartTypeName( xChartType
->getChartType());
393 if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_AREA
))
395 aResult
= SELECT_IMAGE( IMG_TYPE_AREA
, bHC
);
397 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN
))
400 aResult
= SELECT_IMAGE( IMG_TYPE_BAR
, bHC
);
402 aResult
= SELECT_IMAGE( IMG_TYPE_COLUMN
, bHC
);
404 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_LINE
))
406 aResult
= SELECT_IMAGE( IMG_TYPE_LINE
, bHC
);
408 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_SCATTER
))
410 aResult
= SELECT_IMAGE( IMG_TYPE_XY
, bHC
);
412 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_PIE
))
414 aResult
= SELECT_IMAGE( IMG_TYPE_PIE
, bHC
);
416 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_NET
)
417 || aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET
) )
419 aResult
= SELECT_IMAGE( IMG_TYPE_NET
, bHC
);
421 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK
))
423 // @todo: correct image for candle-stick type
424 aResult
= SELECT_IMAGE( IMG_TYPE_STOCK
, bHC
);
426 else if( aChartTypeName
.equals( CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE
))
428 aResult
= SELECT_IMAGE( IMG_TYPE_BUBBLE
, bHC
);
434 struct applyChangesFunctor
: public ::std::unary_function
< ::boost::shared_ptr
< SeriesHeader
>, void >
436 void operator() ( ::boost::shared_ptr
< SeriesHeader
> spHeader
)
438 spHeader
->applyChanges();
443 // ----------------------------------------
448 /** returns false, if no header as the focus.
450 If a header has the focus, true is returned and the index of the header
451 with focus is set at pIndex if pOutIndex is not 0.
453 bool lcl_SeriesHeaderHasFocus(
454 const ::std::vector
< ::boost::shared_ptr
< ::chart::impl::SeriesHeader
> > & rSeriesHeader
,
455 sal_Int32
* pOutIndex
= 0 )
457 sal_Int32 nIndex
= 0;
458 for( ::std::vector
< ::boost::shared_ptr
< ::chart::impl::SeriesHeader
> >::const_iterator
aIt( rSeriesHeader
.begin());
459 aIt
!= rSeriesHeader
.end(); ++aIt
, ++nIndex
)
461 if( (*aIt
)->HasFocus())
471 sal_Int32
lcl_getColumnInDataOrHeader(
472 USHORT nCol
, const ::std::vector
< ::boost::shared_ptr
< ::chart::impl::SeriesHeader
> > & rSeriesHeader
)
474 sal_Int32 nColIdx
= 0;
475 bool bHeaderHasFocus( lcl_SeriesHeaderHasFocus( rSeriesHeader
, &nColIdx
));
477 if( bHeaderHasFocus
)
478 nColIdx
= lcl_getColumnInData( static_cast< USHORT
>( rSeriesHeader
[nColIdx
]->GetStartColumn()));
480 nColIdx
= lcl_getColumnInData( nCol
);
485 } // anonymous namespace
488 DataBrowser::DataBrowser( Window
* pParent
, const ResId
& rId
, bool bLiveUpdate
) :
489 ::svt::EditBrowseBox( pParent
, rId
, EBBF_SMART_TAB_TRAVEL
| EBBF_HANDLE_COLUMN_TEXT
, BROWSER_STANDARD_FLAGS
),
491 m_bIsReadOnly( false ),
493 m_bLiveUpdate( bLiveUpdate
),
494 m_bDataValid( true ),
495 m_aNumberEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER
),
496 m_aTextEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER
),
497 m_rNumberEditController( new ::svt::FormattedFieldCellController( & m_aNumberEditField
)),
498 m_rTextEditController( new ::svt::EditCellController( & m_aTextEditField
))
501 ::rtl::math::setNan( & fNan
);
502 m_aNumberEditField
.SetDefaultValue( fNan
);
503 m_aNumberEditField
.TreatAsNumber( TRUE
);
508 DataBrowser::~DataBrowser()
512 bool DataBrowser::MayInsertRow() const
514 return ! IsReadOnly()
515 && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders
));
518 bool DataBrowser::MayInsertColumn() const
520 return ! IsReadOnly();
523 bool DataBrowser::MayDeleteRow() const
525 return ! IsReadOnly()
526 && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders
))
527 && ( GetCurRow() >= 0 )
528 && ( GetRowCount() > 1 );
531 bool DataBrowser::MayDeleteColumn() const
533 // if a series header has the focus
534 if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders
))
537 return ! IsReadOnly()
538 && ( GetCurColumnId() > 1 )
539 && ( ColCount() > 2 );
542 bool DataBrowser::MaySwapRows() const
544 return ! IsReadOnly()
545 && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders
))
546 && ( GetCurRow() >= 0 )
547 && ( GetCurRow() < GetRowCount() - 1 );
550 bool DataBrowser::MaySwapColumns() const
552 // if a series header (except the last one) has the focus
554 sal_Int32
nColIndex(0);
555 if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders
, &nColIndex
))
556 return (static_cast< sal_uInt32
>( nColIndex
) < (m_aSeriesHeaders
.size() - 1));
559 return ! IsReadOnly()
560 && ( GetCurColumnId() > 1 )
561 && ( GetCurColumnId() < ColCount() - 1 );
564 // bool DataBrowser::MaySortRow() const
566 // // not implemented
568 // // return ! IsReadOnly() && ( GetCurRow() >= 0 );
571 // bool DataBrowser::MaySortColumn() const
573 // // not implemented
575 // // return ! IsReadOnly() && ( GetCurColumnId() > 1 );
578 void DataBrowser::clearHeaders()
580 ::std::for_each( m_aSeriesHeaders
.begin(), m_aSeriesHeaders
.end(), impl::applyChangesFunctor());
581 m_aSeriesHeaders
.clear();
584 void DataBrowser::RenewTable()
586 if( ! m_apDataBrowserModel
.get())
589 long nOldRow
= GetCurRow();
590 USHORT nOldColId
= GetCurColumnId();
592 BOOL bLastUpdateMode
= GetUpdateMode();
593 SetUpdateMode( FALSE
);
601 RowRemoved( 1, GetRowCount() );
604 InsertHandleColumn( static_cast< sal_uInt16
>(
605 GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() ));
607 const sal_Int32 nDefaultColumnWidth
= 94;
609 sal_Int32
nColumnWidth( GetDataWindow().LogicToPixel( Size( nDefaultColumnWidth
, 0 )).getWidth());
610 sal_Int32 nColumnCount
= m_apDataBrowserModel
->getColumnCount();
611 // nRowCount is a member of a base class
612 sal_Int32 nRowCountLocal
= m_apDataBrowserModel
->getMaxRowCount();
613 for( sal_Int32 nColIdx
=1; nColIdx
<=nColumnCount
; ++nColIdx
)
615 InsertDataColumn( static_cast< sal_uInt16
>( nColIdx
), GetColString( nColIdx
), nColumnWidth
);
618 RowInserted( 1, nRowCountLocal
);
619 GoToRow( ::std::min( nOldRow
, GetRowCount() - 1 ));
620 GoToColumnId( ::std::min( nOldColId
, static_cast< USHORT
>( ColCount() - 1 )));
622 Window
* pWin
= this->GetParent();
626 // fill series headers
628 const DataBrowserModel::tDataHeaderVector
& aHeaders( m_apDataBrowserModel
->getDataHeaders());
629 Link
aFocusLink( LINK( this, DataBrowser
, SeriesHeaderGotFocus
));
630 Link
aSeriesHeaderChangedLink( LINK( this, DataBrowser
, SeriesHeaderChanged
));
631 bool bIsHighContrast
= pWin
? (pWin
->GetDisplayBackground().GetColor().IsDark()) : false;
633 for( DataBrowserModel::tDataHeaderVector::const_iterator
aIt( aHeaders
.begin());
634 aIt
!= aHeaders
.end(); ++aIt
)
636 ::boost::shared_ptr
< impl::SeriesHeader
> spHeader( new impl::SeriesHeader( pWin
));
637 Reference
< beans::XPropertySet
> xSeriesProp( aIt
->m_xDataSeries
, uno::UNO_QUERY
);
638 sal_Int32 nColor
= 0;
639 // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc.
640 if( xSeriesProp
.is() &&
641 ( xSeriesProp
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor
))
642 spHeader
->SetColor( Color( nColor
));
643 spHeader
->SetChartType( aIt
->m_xChartType
, aIt
->m_bSwapXAndYAxis
, bIsHighContrast
);
644 spHeader
->SetSeriesName(
645 String( DataSeriesHelper::getDataSeriesLabel(
647 (aIt
->m_xChartType
.is() ?
648 aIt
->m_xChartType
->getRoleOfSequenceForSeriesLabel() :
649 OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
650 // index is 1-based, as 0 is for the column that contains the row-numbers
651 spHeader
->SetRange( aIt
->m_nStartColumn
+ 1, aIt
->m_nEndColumn
+ 1 );
652 spHeader
->SetGetFocusHdl( aFocusLink
);
653 spHeader
->SetEditChangedHdl( aSeriesHeaderChangedLink
);
654 m_aSeriesHeaders
.push_back( spHeader
);
657 ImplAdjustHeaderControls();
659 SetUpdateMode( bLastUpdateMode
);
664 String
DataBrowser::GetColString( sal_Int32 nColumnId
) const
666 OSL_ASSERT( m_apDataBrowserModel
.get());
668 return String( m_apDataBrowserModel
->getRoleOfColumn( static_cast< sal_Int32
>( nColumnId
) - 1 ));
672 String
DataBrowser::GetRowString( sal_Int32 nRow
) const
674 return String::CreateFromInt32( nRow
+ 1 );
677 String
DataBrowser::GetCellText( long nRow
, USHORT nColumnId
) const
683 aResult
= GetRowString( static_cast< sal_Int32
>( nRow
));
685 else if( nRow
>= 0 &&
686 m_apDataBrowserModel
.get())
688 sal_Int32 nColIndex
= static_cast< sal_Int32
>( nColumnId
) - 1;
690 if( m_apDataBrowserModel
->getCellType( nColIndex
, nRow
) == DataBrowserModel::NUMBER
)
692 double fData( m_apDataBrowserModel
->getCellNumber( nColIndex
, nRow
));
693 sal_Int32 nLabelColor
;
694 bool bColorChanged
= false;
696 if( ! ::rtl::math::isNan( fData
) &&
697 m_spNumberFormatterWrapper
.get() )
698 aResult
= String( m_spNumberFormatterWrapper
->getFormattedString(
699 GetNumberFormatKey( nRow
, nColumnId
),
700 fData
, nLabelColor
, bColorChanged
));
704 OSL_ASSERT( m_apDataBrowserModel
->getCellType( nColIndex
, nRow
) == DataBrowserModel::TEXT
);
705 aResult
= m_apDataBrowserModel
->getCellText( nColIndex
, nRow
);
712 double DataBrowser::GetCellNumber( long nRow
, USHORT nColumnId
) const
715 ::rtl::math::setNan( & fResult
);
717 if(( nColumnId
>= 1 ) && ( nRow
>= 0 ) &&
718 m_apDataBrowserModel
.get())
720 fResult
= m_apDataBrowserModel
->getCellNumber(
721 static_cast< sal_Int32
>( nColumnId
) - 1, nRow
);
727 void DataBrowser::Resize()
729 BOOL bLastUpdateMode
= GetUpdateMode();
730 SetUpdateMode( FALSE
);
732 ::svt::EditBrowseBox::Resize();
733 ImplAdjustHeaderControls();
734 SetUpdateMode( bLastUpdateMode
);
737 bool DataBrowser::SetReadOnly( bool bNewState
)
739 bool bResult
= m_bIsReadOnly
;
741 if( m_bIsReadOnly
!= bNewState
)
743 m_bIsReadOnly
= bNewState
;
751 bool DataBrowser::IsReadOnly() const
753 return m_bIsReadOnly
;
757 void DataBrowser::SetClean()
762 void DataBrowser::SetDirty()
768 void DataBrowser::CursorMoved()
770 EditBrowseBox::CursorMoved();
772 if( GetUpdateMode() && m_aCursorMovedHdlLink
.IsSet())
773 m_aCursorMovedHdlLink
.Call( this );
776 void DataBrowser::SetCellModifiedHdl( const Link
& rLink
)
778 m_aCellModifiedLink
= rLink
;
781 void DataBrowser::MouseButtonDown( const BrowserMouseEvent
& rEvt
)
786 EditBrowseBox::MouseButtonDown( rEvt
);
789 void DataBrowser::ShowWarningBox()
791 WarningBox( this, WinBits( WB_OK
),
792 String( SchResId( STR_INVALID_NUMBER
))).Execute();
795 bool DataBrowser::ShowQueryBox()
797 QueryBox
* pQueryBox
= new QueryBox( this, WB_YES_NO
, String( SchResId( STR_DATA_EDITOR_INCORRECT_INPUT
)));
799 return ( pQueryBox
->Execute() == RET_YES
);
802 bool DataBrowser::IsDataValid()
805 const sal_Int32 nRow
= lcl_getRowInData( GetCurRow());
806 const sal_Int32 nCol
= lcl_getColumnInData( GetCurColumnId());
808 if( m_apDataBrowserModel
->getCellType( nCol
, nRow
) == DataBrowserModel::NUMBER
)
810 sal_uInt32 nDummy
= 0;
812 String
aText( m_aNumberEditField
.GetText());
814 if( aText
.Len() > 0 &&
815 m_spNumberFormatterWrapper
.get() &&
816 m_spNumberFormatterWrapper
->getSvNumberFormatter() &&
817 ! m_spNumberFormatterWrapper
->getSvNumberFormatter()->IsNumberFormat(
818 aText
, nDummy
, fDummy
))
827 bool DataBrowser::IsEnableItem()
832 void DataBrowser::CellModified()
834 m_bDataValid
= IsDataValid();
836 if( m_aCellModifiedLink
.IsSet())
837 m_aCursorMovedHdlLink
.Call( this );
840 void DataBrowser::SetDataFromModel(
841 const Reference
< chart2::XChartDocument
> & xChartDoc
,
842 const Reference
< uno::XComponentContext
> & xContext
)
846 m_xChartDoc
.set( xChartDoc
);
850 Reference
< util::XCloneable
> xCloneable( xChartDoc
, uno::UNO_QUERY
);
852 m_xChartDoc
.set( xCloneable
->createClone(), uno::UNO_QUERY
);
855 m_apDataBrowserModel
.reset( new DataBrowserModel( m_xChartDoc
, xContext
));
856 m_spNumberFormatterWrapper
.reset(
857 new NumberFormatterWrapper(
858 Reference
< util::XNumberFormatsSupplier
>( m_xChartDoc
, uno::UNO_QUERY
)));
862 const sal_Int32 nColCnt
= m_apDataBrowserModel
->getColumnCount();
863 const sal_Int32 nRowCnt
= m_apDataBrowserModel
->getMaxRowCount();
864 if( nRowCnt
&& nColCnt
)
872 void DataBrowser::InsertColumn()
874 sal_Int32 nColIdx
= lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders
);
877 m_apDataBrowserModel
.get())
879 // save changes made to edit-field
883 m_apDataBrowserModel
->insertDataSeries( nColIdx
);
888 void DataBrowser::RemoveColumn()
890 sal_Int32 nColIdx
= lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders
);
893 m_apDataBrowserModel
.get())
895 // save changes made to edit-field
900 m_apDataBrowserModel
->removeDataSeries( nColIdx
);
905 void DataBrowser::InsertRow()
907 sal_Int32 nRowIdx
= lcl_getRowInData( GetCurRow());
910 m_apDataBrowserModel
.get())
912 // save changes made to edit-field
916 m_apDataBrowserModel
->insertDataPointForAllSeries( nRowIdx
);
921 void DataBrowser::RemoveRow()
923 sal_Int32 nRowIdx
= lcl_getRowInData( GetCurRow());
926 m_apDataBrowserModel
.get())
928 // save changes made to edit-field
933 m_apDataBrowserModel
->removeDataPointForAllSeries( nRowIdx
);
938 void DataBrowser::SwapColumn()
940 sal_Int32 nColIdx
= lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders
);
943 m_apDataBrowserModel
.get())
945 // save changes made to edit-field
949 m_apDataBrowserModel
->swapDataSeries( nColIdx
);
951 // keep cursor in swapped column
952 if( GetCurColumnId() < ColCount() - 1 )
954 Dispatch( BROWSER_CURSORRIGHT
);
960 void DataBrowser::SwapRow()
962 sal_Int32 nRowIdx
= lcl_getRowInData( GetCurRow());
965 m_apDataBrowserModel
.get())
967 // save changes made to edit-field
971 m_apDataBrowserModel
->swapDataPointForAllSeries( nRowIdx
);
973 // keep cursor in swapped row
974 if( GetCurRow() < GetRowCount() - 1 )
976 Dispatch( BROWSER_CURSORDOWN
);
982 void DataBrowser::SetCursorMovedHdl( const Link
& rLink
)
984 m_aCursorMovedHdlLink
= rLink
;
987 // implementations for ::svt::EditBrowseBox (pure virtual methods)
988 void DataBrowser::PaintCell(
989 OutputDevice
& rDev
, const Rectangle
& rRect
, sal_uInt16 nColumnId
) const
991 Point
aPos( rRect
.TopLeft());
994 String aText
= GetCellText( m_nSeekRow
, nColumnId
);
995 Size
TxtSize( GetDataWindow().GetTextWidth( aText
), GetDataWindow().GetTextHeight());
998 if( aPos
.X() < rRect
.Right() || aPos
.X() + TxtSize
.Width() > rRect
.Right() ||
999 aPos
.Y() < rRect
.Top() || aPos
.Y() + TxtSize
.Height() > rRect
.Bottom())
1000 rDev
.SetClipRegion( rRect
);
1002 // allow for a disabled control ...
1003 sal_Bool bEnabled
= IsEnabled();
1004 Color aOriginalColor
= rDev
.GetTextColor();
1006 rDev
.SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
1009 // if( nColumnId == 1 )
1011 // rDev.SetFillColor( Color( 0xff, 0xff, 0xff ));
1012 // else if( nColumnId == 2 )
1014 // rDev.SetFillColor( Color( 0xf0, 0xf0, 0xff ));
1017 // rDev.SetFillColor( Color( 0xff, 0xff, 0xf0 ));
1019 // rDev.DrawRect( rRect );
1022 rDev
.DrawText( aPos
, aText
);
1024 // reset the color (if necessary)
1026 rDev
.SetTextColor( aOriginalColor
);
1028 if( rDev
.IsClipRegion())
1029 rDev
.SetClipRegion();
1032 sal_Bool
DataBrowser::SeekRow( long nRow
)
1034 if( ! EditBrowseBox::SeekRow( nRow
))
1045 sal_Bool
DataBrowser::IsTabAllowed( sal_Bool bForward
) const
1047 long nRow
= GetCurRow();
1048 long nCol
= GetCurColumnId();
1050 // column 0 is header-column
1051 long nBadCol
= bForward
1052 ? GetColumnCount() - 1
1054 long nBadRow
= bForward
1060 const_cast< DataBrowser
* >( this )->ShowWarningBox();
1064 return ( nRow
!= nBadRow
||
1068 ::svt::CellController
* DataBrowser::GetController( long nRow
, sal_uInt16 nCol
)
1073 if( CellContainsNumbers( nRow
, nCol
))
1075 m_aNumberEditField
.UseInputStringForFormatting();
1076 m_aNumberEditField
.SetFormatKey( GetNumberFormatKey( nRow
, nCol
));
1077 return m_rNumberEditController
;
1080 return m_rTextEditController
;
1083 void DataBrowser::InitController(
1084 ::svt::CellControllerRef
& rController
, long nRow
, sal_uInt16 nCol
)
1086 if( rController
== m_rTextEditController
)
1088 String
aText( GetCellText( nRow
, nCol
) );
1089 m_aTextEditField
.SetText( aText
);
1090 m_aTextEditField
.SetSelection( Selection( 0, aText
.Len() ));
1092 else if( rController
== m_rNumberEditController
)
1094 // treat invalid and empty text as Nan
1095 m_aNumberEditField
.EnableNotANumber( true );
1096 if( ::rtl::math::isNan( GetCellNumber( nRow
, nCol
)))
1097 m_aNumberEditField
.SetTextValue( String());
1099 m_aNumberEditField
.SetValue( GetCellNumber( nRow
, nCol
) );
1100 String
aText( m_aNumberEditField
.GetText());
1101 m_aNumberEditField
.SetSelection( Selection( 0, aText
.Len()));
1105 DBG_ERROR( "Invalid Controller" );
1109 bool DataBrowser::CellContainsNumbers( sal_Int32 nRow
, sal_uInt16 nCol
) const
1111 if( ! m_apDataBrowserModel
.get())
1113 return (m_apDataBrowserModel
->getCellType( lcl_getColumnInData( nCol
), lcl_getRowInData( nRow
)) ==
1114 DataBrowserModel::NUMBER
);
1117 sal_uInt32
DataBrowser::GetNumberFormatKey( sal_Int32 nRow
, sal_uInt16 nCol
) const
1119 if( ! m_apDataBrowserModel
.get())
1121 return m_apDataBrowserModel
->getNumberFormatKey( lcl_getColumnInData( nCol
), lcl_getRowInData( nRow
));
1124 sal_Bool
DataBrowser::SaveModified()
1126 if( ! IsModified() )
1129 sal_Bool bChangeValid
= sal_True
;
1131 const sal_Int32 nRow
= lcl_getRowInData( GetCurRow());
1132 const sal_Int32 nCol
= lcl_getColumnInData( GetCurColumnId());
1134 DBG_ASSERT( nRow
>= 0 || nCol
>= 0, "This cell should not be modified!" );
1136 switch( m_apDataBrowserModel
->getCellType( nCol
, nRow
))
1138 case DataBrowserModel::NUMBER
:
1140 sal_uInt32 nDummy
= 0;
1141 double fDummy
= 0.0;
1142 String
aText( m_aNumberEditField
.GetText());
1143 // an empty string is valid, if no numberformatter exists, all
1144 // values are treated as valid
1145 if( aText
.Len() > 0 &&
1146 m_spNumberFormatterWrapper
.get() &&
1147 m_spNumberFormatterWrapper
->getSvNumberFormatter() &&
1148 ! m_spNumberFormatterWrapper
->getSvNumberFormatter()->IsNumberFormat(
1149 aText
, nDummy
, fDummy
))
1151 bChangeValid
= sal_False
;
1155 double fData
= m_aNumberEditField
.GetValue();
1156 bChangeValid
= m_apDataBrowserModel
->setCellNumber( nCol
, nRow
, fData
);
1160 case DataBrowserModel::TEXT
:
1162 OUString
aText( m_aTextEditField
.GetText());
1163 bChangeValid
= m_apDataBrowserModel
->setCellText( nCol
, nRow
, aText
);
1168 // the first valid change changes this to true
1171 RowModified( GetCurRow(), GetCurColumnId());
1172 ::svt::CellController
* pCtrl
= GetController( GetCurRow(), GetCurColumnId());
1174 pCtrl
->ClearModified();
1178 return bChangeValid
;
1181 bool DataBrowser::EndEditing()
1186 // apply changes made to series headers
1187 ::std::for_each( m_aSeriesHeaders
.begin(), m_aSeriesHeaders
.end(), impl::applyChangesFunctor());
1192 return ShowQueryBox();
1195 sal_Int16
DataBrowser::GetFirstVisibleColumNumber() const
1197 return GetFirstVisibleColNumber();
1200 void DataBrowser::ColumnResized( USHORT nColId
)
1202 BOOL bLastUpdateMode
= GetUpdateMode();
1203 SetUpdateMode( FALSE
);
1205 EditBrowseBox::ColumnResized( nColId
);
1206 ImplAdjustHeaderControls();
1207 SetUpdateMode( bLastUpdateMode
);
1210 // virtual void MouseMove( const MouseEvent& rEvt );
1212 void DataBrowser::EndScroll()
1214 BOOL bLastUpdateMode
= GetUpdateMode();
1215 SetUpdateMode( FALSE
);
1217 EditBrowseBox::EndScroll();
1218 RenewSeriesHeaders();
1220 SetUpdateMode( bLastUpdateMode
);
1223 void DataBrowser::RenewSeriesHeaders()
1225 Window
* pWin
= this->GetParent();
1230 DataBrowserModel::tDataHeaderVector
aHeaders( m_apDataBrowserModel
->getDataHeaders());
1231 Link
aFocusLink( LINK( this, DataBrowser
, SeriesHeaderGotFocus
));
1232 Link
aSeriesHeaderChangedLink( LINK( this, DataBrowser
, SeriesHeaderChanged
));
1233 bool bIsHighContrast
= pWin
? (pWin
->GetDisplayBackground().GetColor().IsDark()) : false;
1235 for( DataBrowserModel::tDataHeaderVector::const_iterator
aIt( aHeaders
.begin());
1236 aIt
!= aHeaders
.end(); ++aIt
)
1238 ::boost::shared_ptr
< impl::SeriesHeader
> spHeader( new impl::SeriesHeader( pWin
));
1239 Reference
< beans::XPropertySet
> xSeriesProp( aIt
->m_xDataSeries
, uno::UNO_QUERY
);
1240 sal_Int32 nColor
= 0;
1241 if( xSeriesProp
.is() &&
1242 ( xSeriesProp
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor
))
1243 spHeader
->SetColor( Color( nColor
));
1244 spHeader
->SetChartType( aIt
->m_xChartType
, aIt
->m_bSwapXAndYAxis
, bIsHighContrast
);
1245 spHeader
->SetSeriesName(
1246 String( DataSeriesHelper::getDataSeriesLabel(
1248 (aIt
->m_xChartType
.is() ?
1249 aIt
->m_xChartType
->getRoleOfSequenceForSeriesLabel() :
1250 OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
1251 spHeader
->SetRange( aIt
->m_nStartColumn
+ 1, aIt
->m_nEndColumn
+ 1 );
1252 spHeader
->SetGetFocusHdl( aFocusLink
);
1253 spHeader
->SetEditChangedHdl( aSeriesHeaderChangedLink
);
1254 m_aSeriesHeaders
.push_back( spHeader
);
1257 ImplAdjustHeaderControls();
1260 void DataBrowser::ImplAdjustHeaderControls()
1262 sal_uInt16 nColCount
= this->GetColumnCount();
1263 sal_uInt32 nCurrentPos
= this->GetPosPixel().getX();
1264 sal_uInt32 nMaxPos
= nCurrentPos
+ this->GetOutputSizePixel().getWidth();
1265 sal_uInt32 nStartPos
= nCurrentPos
;
1267 // width of header column
1268 nCurrentPos
+= this->GetColumnWidth( 0 );
1269 tSeriesHeaderContainer::iterator
aIt( m_aSeriesHeaders
.begin());
1270 sal_uInt16 i
= this->GetFirstVisibleColumNumber();
1271 while( (aIt
!= m_aSeriesHeaders
.end()) && ((*aIt
)->GetStartColumn() < i
) )
1273 for( ; i
< nColCount
&& aIt
!= m_aSeriesHeaders
.end(); ++i
)
1275 if( (*aIt
)->GetStartColumn() == i
)
1276 nStartPos
= nCurrentPos
;
1278 nCurrentPos
+= (this->GetColumnWidth( i
));
1280 if( (*aIt
)->GetEndColumn() == i
)
1282 if( nStartPos
< nMaxPos
)
1284 (*aIt
)->SetPixelPosX( nStartPos
+ 2 );
1285 (*aIt
)->SetPixelWidth( nCurrentPos
- nStartPos
- 3 );
1288 // do not hide, to get focus events. Move outside the dialog for "hiding"
1289 (*aIt
)->SetPixelPosX( nMaxPos
+ 42 );
1295 IMPL_LINK( DataBrowser
, SeriesHeaderGotFocus
, impl::SeriesHeaderEdit
*, pEdit
)
1299 pEdit
->SetShowWarningBox( !m_bDataValid
);
1306 MakeFieldVisible( GetCurRow(), static_cast< sal_uInt16
>( pEdit
->getStartColumn()), true /* bComplete */ );
1308 m_aCursorMovedHdlLink
.Call( this );
1314 IMPL_LINK( DataBrowser
, SeriesHeaderChanged
, impl::SeriesHeaderEdit
*, pEdit
)
1318 Reference
< chart2::XDataSeries
> xSeries(
1319 m_apDataBrowserModel
->getDataSeriesByColumn( pEdit
->getStartColumn() - 1 ));
1320 Reference
< chart2::data::XDataSource
> xSource( xSeries
, uno::UNO_QUERY
);
1323 Reference
< chart2::XChartType
> xChartType(
1324 m_apDataBrowserModel
->getHeaderForSeries( xSeries
).m_xChartType
);
1325 if( xChartType
.is())
1327 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq(
1328 DataSeriesHelper::getDataSequenceByRole( xSource
, xChartType
->getRoleOfSequenceForSeriesLabel()));
1329 if( xLabeledSeq
.is())
1331 Reference
< container::XIndexReplace
> xIndexReplace( xLabeledSeq
->getLabel(), uno::UNO_QUERY
);
1332 if( xIndexReplace
.is())
1333 xIndexReplace
->replaceByIndex(
1334 0, uno::makeAny( OUString( pEdit
->GetText())));
1342 sal_Int32
DataBrowser::GetTotalWidth() const
1345 for ( USHORT nCol
= 0; nCol
< ColCount(); ++nCol
)
1346 nWidth
+= GetColumnWidth( nCol
);
1347 return static_cast< sal_Int32
>( nWidth
);
1350 } // namespace chart