Bump version to 6.4-15
[LibreOffice.git] / svx / source / fmcomp / gridcell.cxx
blob911d814285e289da3e303851ab2b42cdefaae98b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <memory>
22 #include <sal/macros.h>
23 #include <sal/log.hxx>
24 #include <fmprop.hxx>
25 #include <svx/strings.hrc>
26 #include <svx/fmtools.hxx>
27 #include <gridcell.hxx>
28 #include <gridcols.hxx>
29 #include <sdbdatacolumn.hxx>
31 #include <com/sun/star/awt/LineEndFormat.hpp>
32 #include <com/sun/star/awt/MouseWheelBehavior.hpp>
33 #include <com/sun/star/awt/VisualEffect.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/container/XIndexAccess.hpp>
36 #include <com/sun/star/container/XNamed.hpp>
37 #include <com/sun/star/form/FormComponentType.hpp>
38 #include <com/sun/star/form/XBoundComponent.hpp>
39 #include <com/sun/star/script/XEventAttacherManager.hpp>
40 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
41 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
42 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
43 #include <com/sun/star/sdbc/ColumnValue.hpp>
44 #include <com/sun/star/sdbc/DataType.hpp>
45 #include <com/sun/star/sdbc/SQLException.hpp>
46 #include <com/sun/star/sdbc/XRowSet.hpp>
47 #include <com/sun/star/sdbc/XStatement.hpp>
48 #include <com/sun/star/util/NumberFormat.hpp>
49 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
50 #include <com/sun/star/util/XNumberFormatter.hpp>
51 #include <com/sun/star/util/Time.hpp>
52 #include <com/sun/star/util/Date.hpp>
54 #include <comphelper/numbers.hxx>
55 #include <comphelper/property.hxx>
56 #include <comphelper/servicehelper.hxx>
57 #include <comphelper/string.hxx>
58 #include <comphelper/types.hxx>
59 #include <connectivity/formattedcolumnvalue.hxx>
60 #include <cppuhelper/typeprovider.hxx>
61 #include <i18nlangtag/lang.h>
63 #include <rtl/math.hxx>
64 #include <svtools/calendar.hxx>
65 #include <vcl/fmtfield.hxx>
66 #include <svl/numuno.hxx>
67 #include <svl/zforlist.hxx>
68 #include <svx/dialmgr.hxx>
69 #include <toolkit/helper/vclunohelper.hxx>
70 #include <tools/debug.hxx>
71 #include <tools/diagnose_ex.h>
72 #include <vcl/longcurr.hxx>
73 #include <vcl/settings.hxx>
74 #include <vcl/svapp.hxx>
75 #include <connectivity/dbtools.hxx>
76 #include <connectivity/dbconversion.hxx>
77 #include <connectivity/sqlnode.hxx>
79 #include <math.h>
81 using namespace ::connectivity;
82 using namespace ::svxform;
83 using namespace ::comphelper;
84 using namespace ::svt;
85 using namespace ::com::sun::star;
86 using namespace ::com::sun::star::uno;
87 using namespace ::com::sun::star::sdbc;
88 using namespace ::com::sun::star::sdbcx;
89 using namespace ::com::sun::star::sdb;
90 using namespace ::com::sun::star::beans;
91 using namespace ::com::sun::star::form;
92 using namespace ::dbtools::DBTypeConversion;
93 using namespace ::dbtools;
95 using ::com::sun::star::util::XNumberFormatter;
97 const char INVALIDTEXT[] = "###";
98 const char OBJECTTEXT[] = "<OBJECT>";
101 //= helper
103 namespace
105 LineEnd getModelLineEndSetting( const Reference< XPropertySet >& _rxModel )
107 LineEnd eFormat = LINEEND_LF;
111 sal_Int16 nLineEndFormat = awt::LineEndFormat::LINE_FEED;
113 Reference< XPropertySetInfo > xPSI;
114 if ( _rxModel.is() )
115 xPSI = _rxModel->getPropertySetInfo();
117 OSL_ENSURE( xPSI.is(), "getModelLineEndSetting: invalid column model!" );
118 if ( xPSI.is() && xPSI->hasPropertyByName( FM_PROP_LINEENDFORMAT ) )
120 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_LINEENDFORMAT ) >>= nLineEndFormat );
122 switch ( nLineEndFormat )
124 case awt::LineEndFormat::CARRIAGE_RETURN: eFormat = LINEEND_CR; break;
125 case awt::LineEndFormat::LINE_FEED: eFormat = LINEEND_LF; break;
126 case awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED: eFormat = LINEEND_CRLF; break;
127 default:
128 OSL_FAIL( "getModelLineEndSetting: what's this?" );
132 catch( const Exception& )
134 DBG_UNHANDLED_EXCEPTION("svx");
135 OSL_FAIL( "getModelLineEndSetting: caught an exception!" );
137 return eFormat;
142 //= DbGridColumn
145 CellControllerRef DbGridColumn::s_xEmptyController;
148 void DbGridColumn::CreateControl(sal_Int32 _nFieldPos, const Reference< css::beans::XPropertySet >& xField, sal_Int32 nTypeId)
150 Clear();
152 m_nTypeId = static_cast<sal_Int16>(nTypeId);
153 if (xField != m_xField)
155 // initial setting
156 m_xField = xField;
157 xField->getPropertyValue(FM_PROP_FORMATKEY) >>= m_nFormatKey;
158 m_nFieldPos = static_cast<sal_Int16>(_nFieldPos);
159 m_bReadOnly = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISREADONLY));
160 m_bAutoValue = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_AUTOINCREMENT));
161 m_nFieldType = static_cast<sal_Int16>(::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE)));
163 switch (m_nFieldType)
165 case DataType::DATE:
166 case DataType::TIME:
167 case DataType::TIMESTAMP:
168 case DataType::BIT:
169 case DataType::BOOLEAN:
170 case DataType::TINYINT:
171 case DataType::SMALLINT:
172 case DataType::INTEGER:
173 case DataType::BIGINT:
174 case DataType::FLOAT:
175 case DataType::REAL:
176 case DataType::DOUBLE:
177 case DataType::NUMERIC:
178 case DataType::DECIMAL:
179 m_nAlign = css::awt::TextAlign::RIGHT;
180 m_bNumeric = true;
181 break;
182 default:
183 m_nAlign = css::awt::TextAlign::LEFT;
184 break;
188 std::unique_ptr<DbCellControl> pCellControl;
189 if (m_rParent.IsFilterMode())
191 pCellControl.reset(new DbFilterField(m_rParent.getContext(),*this));
193 else
196 switch (nTypeId)
198 case TYPE_CHECKBOX: pCellControl.reset(new DbCheckBox(*this)); break;
199 case TYPE_COMBOBOX: pCellControl.reset(new DbComboBox(*this)); break;
200 case TYPE_CURRENCYFIELD: pCellControl.reset(new DbCurrencyField(*this)); break;
201 case TYPE_DATEFIELD: pCellControl.reset(new DbDateField(*this)); break;
202 case TYPE_LISTBOX: pCellControl.reset(new DbListBox(*this)); break;
203 case TYPE_NUMERICFIELD: pCellControl.reset(new DbNumericField(*this)); break;
204 case TYPE_PATTERNFIELD: pCellControl.reset(new DbPatternField( *this, m_rParent.getContext() )); break;
205 case TYPE_TEXTFIELD: pCellControl.reset(new DbTextField(*this)); break;
206 case TYPE_TIMEFIELD: pCellControl.reset(new DbTimeField(*this)); break;
207 case TYPE_FORMATTEDFIELD: pCellControl.reset(new DbFormattedField(*this)); break;
208 default:
209 OSL_FAIL("DbGridColumn::CreateControl: Unknown Column");
210 return;
214 Reference< XRowSet > xCur;
215 if (m_rParent.getDataSource())
216 xCur.set(Reference< XInterface >(*m_rParent.getDataSource()), UNO_QUERY);
217 // TODO : the cursor wrapper should use an XRowSet interface, too
219 pCellControl->Init( m_rParent.GetDataWindow(), xCur );
221 // now create the control wrapper
222 auto pTempCellControl = pCellControl.get();
223 if (m_rParent.IsFilterMode())
224 m_pCell = new FmXFilterCell(this, std::unique_ptr<DbFilterField>(static_cast<DbFilterField*>(pCellControl.release())));
225 else
227 switch (nTypeId)
229 case TYPE_CHECKBOX: m_pCell = new FmXCheckBoxCell( this, std::move(pCellControl) ); break;
230 case TYPE_LISTBOX: m_pCell = new FmXListBoxCell( this, std::move(pCellControl) ); break;
231 case TYPE_COMBOBOX: m_pCell = new FmXComboBoxCell( this, std::move(pCellControl) ); break;
232 default:
233 m_pCell = new FmXEditCell( this, std::move(pCellControl) );
236 m_pCell->init();
238 impl_toggleScriptManager_nothrow( true );
240 // only if we use have a bound field, we use a controller for displaying the
241 // window in the grid
242 if (m_xField.is())
243 m_xController = pTempCellControl->CreateController();
247 void DbGridColumn::impl_toggleScriptManager_nothrow( bool _bAttach )
251 Reference< container::XChild > xChild( m_xModel, UNO_QUERY_THROW );
252 Reference< script::XEventAttacherManager > xManager( xChild->getParent(), UNO_QUERY_THROW );
253 Reference< container::XIndexAccess > xContainer( xChild->getParent(), UNO_QUERY_THROW );
255 sal_Int32 nIndexInParent( getElementPos( xContainer, m_xModel ) );
257 Reference< XInterface > xCellInterface( *m_pCell, UNO_QUERY );
258 if ( _bAttach )
259 xManager->attach( nIndexInParent, xCellInterface, makeAny( xCellInterface ) );
260 else
261 xManager->detach( nIndexInParent, xCellInterface );
263 catch( const Exception& )
265 DBG_UNHANDLED_EXCEPTION("svx");
269 void DbGridColumn::UpdateFromField(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter)
271 if (FmXFilterCell* pCell = dynamic_cast<FmXFilterCell*>(m_pCell.get()))
272 pCell->Update();
273 else if (pRow && pRow->IsValid() && m_nFieldPos >= 0 && m_pCell.is() && pRow->HasField(m_nFieldPos))
275 dynamic_cast<FmXDataCell&>(*m_pCell).UpdateFromField( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter );
279 bool DbGridColumn::Commit()
281 bool bResult = true;
282 if (!m_bInSave && m_pCell.is())
284 m_bInSave = true;
285 bResult = m_pCell->Commit();
287 // store the data into the model
288 FmXDataCell* pDataCell = dynamic_cast<FmXDataCell*>( m_pCell.get() );
289 if (bResult && pDataCell)
291 Reference< css::form::XBoundComponent > xComp(m_xModel, UNO_QUERY);
292 if (xComp.is())
293 bResult = xComp->commit();
295 m_bInSave = false;
297 return bResult;
301 DbGridColumn::~DbGridColumn()
303 Clear();
307 void DbGridColumn::setModel(const css::uno::Reference< css::beans::XPropertySet >& _xModel)
309 if ( m_pCell.is() )
310 impl_toggleScriptManager_nothrow( false );
312 m_xModel = _xModel;
314 if ( m_pCell.is() )
315 impl_toggleScriptManager_nothrow( true );
319 void DbGridColumn::Clear()
321 if ( m_pCell.is() )
323 impl_toggleScriptManager_nothrow( false );
325 m_pCell->dispose();
326 m_pCell.clear();
329 m_xController = nullptr;
330 m_xField = nullptr;
332 m_nFormatKey = 0;
333 m_nFieldPos = -1;
334 m_bReadOnly = true;
335 m_bAutoValue = false;
336 m_nFieldType = DataType::OTHER;
340 sal_Int16 DbGridColumn::SetAlignment(sal_Int16 _nAlign)
342 if (_nAlign == -1)
343 { // 'Standard'
344 if (m_xField.is())
346 sal_Int32 nType = 0;
347 m_xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nType;
349 switch (nType)
351 case DataType::NUMERIC:
352 case DataType::DECIMAL:
353 case DataType::DOUBLE:
354 case DataType::REAL:
355 case DataType::BIGINT:
356 case DataType::INTEGER:
357 case DataType::SMALLINT:
358 case DataType::TINYINT:
359 case DataType::DATE:
360 case DataType::TIME:
361 case DataType::TIMESTAMP:
362 _nAlign = css::awt::TextAlign::RIGHT;
363 break;
364 case DataType::BIT:
365 case DataType::BOOLEAN:
366 _nAlign = css::awt::TextAlign::CENTER;
367 break;
368 default:
369 _nAlign = css::awt::TextAlign::LEFT;
370 break;
373 else
374 _nAlign = css::awt::TextAlign::LEFT;
377 m_nAlign = _nAlign;
378 if (m_pCell.is() && m_pCell->isAlignedController())
379 m_pCell->AlignControl(m_nAlign);
381 return m_nAlign;
385 sal_Int16 DbGridColumn::SetAlignmentFromModel(sal_Int16 nStandardAlign)
387 Any aAlign( m_xModel->getPropertyValue(FM_PROP_ALIGN));
388 if (aAlign.hasValue())
390 sal_Int16 nTest = sal_Int16();
391 if (aAlign >>= nTest)
392 nStandardAlign = nTest;
394 return SetAlignment(nStandardAlign);
398 void DbGridColumn::setLock(bool _bLock)
400 if (m_bLocked == _bLock)
401 return;
402 m_bLocked = _bLock;
404 // is the column we represent active ?
405 if (m_bHidden)
406 return; // no, it isn't (or at least it shouldn't be ...)
408 if (m_rParent.GetCurColumnId() == m_nId)
410 m_rParent.DeactivateCell();
411 m_rParent.ActivateCell(m_rParent.GetCurRow(), m_rParent.GetCurColumnId());
416 OUString DbGridColumn::GetCellText(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter) const
418 OUString aText;
419 if (m_pCell.is() && dynamic_cast<const FmXFilterCell*>( m_pCell.get() ) != nullptr)
420 return aText;
422 if (!pRow || !pRow->IsValid())
423 aText = INVALIDTEXT;
424 else if (pRow->HasField(m_nFieldPos))
426 aText = GetCellText( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter );
428 return aText;
432 OUString DbGridColumn::GetCellText(const Reference< css::sdb::XColumn >& xField, const Reference< XNumberFormatter >& xFormatter) const
434 OUString aText;
435 if (xField.is())
437 FmXTextCell* pTextCell = dynamic_cast<FmXTextCell*>( m_pCell.get() );
438 if (pTextCell)
439 aText = pTextCell->GetText(xField, xFormatter);
440 else if (m_bObject)
441 aText = OBJECTTEXT;
443 return aText;
447 Reference< css::sdb::XColumn > DbGridColumn::GetCurrentFieldValue() const
449 Reference< css::sdb::XColumn > xField;
450 const DbGridRowRef xRow = m_rParent.GetCurrentRow();
451 if (xRow.is() && xRow->HasField(m_nFieldPos))
453 xField = xRow->GetField(m_nFieldPos).getColumn();
455 return xField;
459 void DbGridColumn::Paint(OutputDevice& rDev,
460 const tools::Rectangle& rRect,
461 const DbGridRow* pRow,
462 const Reference< XNumberFormatter >& xFormatter)
464 bool bEnabled = ( rDev.GetOutDevType() != OUTDEV_WINDOW )
465 || ( static_cast< vcl::Window& >( rDev ).IsEnabled() );
467 FmXDataCell* pDataCell = dynamic_cast<FmXDataCell*>( m_pCell.get() );
468 if (pDataCell)
470 if (!pRow || !pRow->IsValid())
472 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
473 if ( !bEnabled )
474 nStyle |= DrawTextFlags::Disable;
476 rDev.DrawText(rRect, OUString(INVALIDTEXT), nStyle);
478 else if (m_bAutoValue && pRow->IsNew())
480 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter;
481 if ( !bEnabled )
482 nStyle |= DrawTextFlags::Disable;
484 switch (GetAlignment())
486 case css::awt::TextAlign::RIGHT:
487 nStyle |= DrawTextFlags::Right;
488 break;
489 case css::awt::TextAlign::CENTER:
490 nStyle |= DrawTextFlags::Center;
491 break;
492 default:
493 nStyle |= DrawTextFlags::Left;
496 rDev.DrawText(rRect, SvxResId(RID_STR_AUTOFIELD), nStyle);
498 else if (pRow->HasField(m_nFieldPos))
500 pDataCell->PaintFieldToCell(rDev, rRect, pRow->GetField( m_nFieldPos ).getColumn(), xFormatter);
503 else if (!m_pCell.is())
505 if (!pRow || !pRow->IsValid())
507 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
508 if ( !bEnabled )
509 nStyle |= DrawTextFlags::Disable;
511 rDev.DrawText(rRect, OUString(INVALIDTEXT), nStyle);
513 else if (pRow->HasField(m_nFieldPos) && m_bObject)
515 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
516 if ( !bEnabled )
517 nStyle |= DrawTextFlags::Disable;
518 rDev.DrawText(rRect, OUString(OBJECTTEXT), nStyle);
521 else if ( dynamic_cast<const FmXFilterCell*>( m_pCell.get() ) != nullptr )
522 static_cast< FmXFilterCell* >( m_pCell.get() )->PaintCell( rDev, rRect );
526 void DbGridColumn::ImplInitWindow( vcl::Window const & rParent, const InitWindowFacet _eInitWhat )
528 if ( m_pCell.is() )
529 m_pCell->ImplInitWindow( rParent, _eInitWhat );
533 //= cell controls
536 DbCellControl::DbCellControl( DbGridColumn& _rColumn )
537 :OPropertyChangeListener(m_aMutex)
538 ,m_bTransparent( false )
539 ,m_bAlignedController( true )
540 ,m_bAccessingValueProperty( false )
541 ,m_rColumn( _rColumn )
542 ,m_pPainter( nullptr )
543 ,m_pWindow( nullptr )
545 Reference< XPropertySet > xColModelProps = _rColumn.getModel();
546 if ( !xColModelProps.is() )
547 return;
549 // if our model's format key changes we want to propagate the new value to our windows
550 m_pModelChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, _rColumn.getModel());
552 // be listener for some common properties
553 implDoPropertyListening( FM_PROP_READONLY, false );
554 implDoPropertyListening( FM_PROP_ENABLED, false );
556 // add as listener for all known "value" properties
557 implDoPropertyListening( FM_PROP_VALUE, false );
558 implDoPropertyListening( FM_PROP_STATE, false );
559 implDoPropertyListening( FM_PROP_TEXT, false );
560 implDoPropertyListening( FM_PROP_EFFECTIVE_VALUE, false );
561 implDoPropertyListening( FM_PROP_SELECT_SEQ, false );
562 implDoPropertyListening( FM_PROP_DATE, false );
563 implDoPropertyListening( FM_PROP_TIME, false );
565 // be listener at the bound field as well
568 Reference< XPropertySetInfo > xPSI( xColModelProps->getPropertySetInfo(), UNO_SET_THROW );
569 if ( xPSI->hasPropertyByName( FM_PROP_BOUNDFIELD ) )
571 Reference< XPropertySet > xField;
572 xColModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
573 if ( xField.is() )
575 m_pFieldChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, xField);
576 m_pFieldChangeBroadcaster->addProperty( FM_PROP_ISREADONLY );
580 catch( const Exception& )
582 DBG_UNHANDLED_EXCEPTION("svx");
583 OSL_FAIL( "DbCellControl::doPropertyListening: caught an exception!" );
588 void DbCellControl::implDoPropertyListening(const OUString& _rPropertyName, bool _bWarnIfNotExistent)
592 Reference< XPropertySet > xColModelProps = m_rColumn.getModel();
593 Reference< XPropertySetInfo > xPSI;
594 if ( xColModelProps.is() )
595 xPSI = xColModelProps->getPropertySetInfo();
597 DBG_ASSERT( !_bWarnIfNotExistent || ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) ),
598 "DbCellControl::doPropertyListening: no property set info or non-existent property!" );
600 if ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) )
601 m_pModelChangeBroadcaster->addProperty( _rPropertyName );
603 catch( const Exception& )
605 DBG_UNHANDLED_EXCEPTION("svx");
606 OSL_FAIL( "DbCellControl::doPropertyListening: caught an exception!" );
611 void DbCellControl::doPropertyListening(const OUString& _rPropertyName)
613 implDoPropertyListening( _rPropertyName, true );
616 static void lcl_clearBroadCaster(rtl::Reference<::comphelper::OPropertyChangeMultiplexer>& _pBroadcaster)
618 if ( _pBroadcaster.is() )
620 _pBroadcaster->dispose();
621 _pBroadcaster.clear();
622 // no delete, this is done implicitly
626 DbCellControl::~DbCellControl()
628 lcl_clearBroadCaster(m_pModelChangeBroadcaster);
629 lcl_clearBroadCaster(m_pFieldChangeBroadcaster);
631 m_pWindow.disposeAndClear();
632 m_pPainter.disposeAndClear();
635 void DbCellControl::implValuePropertyChanged( )
637 OSL_ENSURE( !isValuePropertyLocked(),
638 "DbCellControl::implValuePropertyChanged: not to be called with the value property locked!" );
640 if ( m_pWindow )
642 if ( m_rColumn.getModel().is() )
643 updateFromModel( m_rColumn.getModel() );
648 void DbCellControl::implAdjustGenericFieldSetting( const Reference< XPropertySet >& /*_rxModel*/ )
650 // nothing to do here
654 void DbCellControl::_propertyChanged(const PropertyChangeEvent& _rEvent)
656 SolarMutexGuard aGuard;
658 Reference< XPropertySet > xSourceProps( _rEvent.Source, UNO_QUERY );
660 if ( _rEvent.PropertyName == FM_PROP_VALUE
661 || _rEvent.PropertyName == FM_PROP_STATE
662 || _rEvent.PropertyName == FM_PROP_TEXT
663 || _rEvent.PropertyName == FM_PROP_EFFECTIVE_VALUE
664 || _rEvent.PropertyName == FM_PROP_SELECT_SEQ
665 || _rEvent.PropertyName == FM_PROP_DATE
666 || _rEvent.PropertyName == FM_PROP_TIME
668 { // it was one of the known "value" properties
669 if ( !isValuePropertyLocked() )
671 implValuePropertyChanged( );
674 else if ( _rEvent.PropertyName == FM_PROP_READONLY )
676 implAdjustReadOnly( xSourceProps, true);
678 else if ( _rEvent.PropertyName == FM_PROP_ISREADONLY )
680 bool bReadOnly = true;
681 _rEvent.NewValue >>= bReadOnly;
682 m_rColumn.SetReadOnly(bReadOnly);
683 implAdjustReadOnly( xSourceProps, false);
685 else if ( _rEvent.PropertyName == FM_PROP_ENABLED )
687 implAdjustEnabled( xSourceProps );
689 else
690 implAdjustGenericFieldSetting( xSourceProps );
694 bool DbCellControl::Commit()
696 // lock the listening for value property changes
697 lockValueProperty();
698 // commit the content of the control into the model's value property
699 bool bReturn = false;
702 bReturn = commitControl();
704 catch( const Exception& )
706 DBG_UNHANDLED_EXCEPTION("svx");
708 // unlock the listening for value property changes
709 unlockValueProperty();
710 // outta here
711 return bReturn;
715 void DbCellControl::ImplInitWindow( vcl::Window const & rParent, const InitWindowFacet _eInitWhat )
717 vcl::Window* pWindows[] = { m_pPainter, m_pWindow };
719 if (_eInitWhat & InitWindowFacet::WritingMode)
721 for (vcl::Window* pWindow : pWindows)
723 if (pWindow)
724 pWindow->EnableRTL(rParent.IsRTLEnabled());
728 if (_eInitWhat & InitWindowFacet::Font)
730 for (vcl::Window* pWindow : pWindows)
732 if (!pWindow)
733 continue;
735 pWindow->SetZoom(rParent.GetZoom());
737 const StyleSettings& rStyleSettings = pWindow->GetSettings().GetStyleSettings();
738 vcl::Font aFont = rStyleSettings.GetFieldFont();
739 aFont.SetTransparent(isTransparent());
741 if (rParent.IsControlFont())
743 pWindow->SetControlFont(rParent.GetControlFont());
744 aFont.Merge(rParent.GetControlFont());
746 else
747 pWindow->SetControlFont();
749 pWindow->SetZoomedPointFont(*pWindow, aFont); // FIXME RenderContext
753 if ((_eInitWhat & InitWindowFacet::Font) || (_eInitWhat & InitWindowFacet::Foreground))
755 Color aTextColor(rParent.IsControlForeground() ? rParent.GetControlForeground() : rParent.GetTextColor());
757 bool bTextLineColor = rParent.IsTextLineColor();
758 Color aTextLineColor(rParent.GetTextLineColor());
760 for (vcl::Window* pWindow : pWindows)
762 if (pWindow)
764 pWindow->SetTextColor(aTextColor);
765 if (rParent.IsControlForeground())
766 pWindow->SetControlForeground(aTextColor);
768 if (bTextLineColor)
769 pWindow->SetTextLineColor();
770 else
771 pWindow->SetTextLineColor(aTextLineColor);
776 if (_eInitWhat & InitWindowFacet::Background)
778 if (rParent.IsControlBackground())
780 Color aColor(rParent.GetControlBackground());
781 for (vcl::Window* pWindow : pWindows)
783 if (pWindow)
785 if (isTransparent())
786 pWindow->SetBackground();
787 else
789 pWindow->SetBackground(aColor);
790 pWindow->SetControlBackground(aColor);
792 pWindow->SetFillColor(aColor);
796 else
798 if (m_pPainter)
800 if (isTransparent())
801 m_pPainter->SetBackground();
802 else
803 m_pPainter->SetBackground(rParent.GetBackground());
804 m_pPainter->SetFillColor(rParent.GetFillColor());
807 if (m_pWindow)
809 if (isTransparent())
810 m_pWindow->SetBackground(rParent.GetBackground());
811 else
812 m_pWindow->SetFillColor(rParent.GetFillColor());
819 void DbCellControl::implAdjustReadOnly( const Reference< XPropertySet >& _rxModel,bool i_bReadOnly )
821 DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustReadOnly: not to be called without window!" );
822 DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustReadOnly: invalid model!" );
823 if ( m_pWindow && _rxModel.is() )
825 Edit* pEditWindow = dynamic_cast< Edit* >( m_pWindow.get() );
826 if ( pEditWindow )
828 bool bReadOnly = m_rColumn.IsReadOnly();
829 if ( !bReadOnly )
831 _rxModel->getPropertyValue( i_bReadOnly ? OUString(FM_PROP_READONLY) : OUString(FM_PROP_ISREADONLY)) >>= bReadOnly;
833 static_cast< Edit* >( m_pWindow.get() )->SetReadOnly( bReadOnly );
839 void DbCellControl::implAdjustEnabled( const Reference< XPropertySet >& _rxModel )
841 DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustEnabled: not to be called without window!" );
842 DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustEnabled: invalid model!" );
843 if ( m_pWindow && _rxModel.is() )
845 bool bEnable = true;
846 _rxModel->getPropertyValue( FM_PROP_ENABLED ) >>= bEnable;
847 m_pWindow->Enable( bEnable );
852 void DbCellControl::Init( vcl::Window& rParent, const Reference< XRowSet >& _rxCursor )
854 ImplInitWindow( rParent, InitWindowFacet::All );
856 if ( m_pWindow )
858 // align the control
859 if ( isAlignedController() )
860 AlignControl( m_rColumn.GetAlignment() );
864 // some other common properties
865 Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW );
866 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
868 if ( xModelPSI->hasPropertyByName( FM_PROP_READONLY ) )
870 implAdjustReadOnly( xModel,true );
873 if ( xModelPSI->hasPropertyByName( FM_PROP_ENABLED ) )
875 implAdjustEnabled( xModel );
878 if ( xModelPSI->hasPropertyByName( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) )
880 sal_Int16 nWheelBehavior = css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY;
881 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) >>= nWheelBehavior );
882 MouseWheelBehaviour nVclSetting = MouseWheelBehaviour::FocusOnly;
883 switch ( nWheelBehavior )
885 case css::awt::MouseWheelBehavior::SCROLL_DISABLED: nVclSetting = MouseWheelBehaviour::Disable; break;
886 case css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY: nVclSetting = MouseWheelBehaviour::FocusOnly; break;
887 case css::awt::MouseWheelBehavior::SCROLL_ALWAYS: nVclSetting = MouseWheelBehaviour::ALWAYS; break;
888 default:
889 OSL_FAIL( "DbCellControl::Init: invalid MouseWheelBehavior!" );
890 break;
893 AllSettings aSettings = m_pWindow->GetSettings();
894 MouseSettings aMouseSettings = aSettings.GetMouseSettings();
895 aMouseSettings.SetWheelBehavior( nVclSetting );
896 aSettings.SetMouseSettings( aMouseSettings );
897 m_pWindow->SetSettings( aSettings, true );
900 catch( const Exception& )
902 DBG_UNHANDLED_EXCEPTION("svx");
905 m_xCursor = _rxCursor;
906 if ( m_rColumn.getModel().is() )
907 updateFromModel( m_rColumn.getModel() );
911 void DbCellControl::SetTextLineColor()
913 if (m_pWindow)
914 m_pWindow->SetTextLineColor();
915 if (m_pPainter)
916 m_pPainter->SetTextLineColor();
920 void DbCellControl::SetTextLineColor(const Color& _rColor)
922 if (m_pWindow)
923 m_pWindow->SetTextLineColor(_rColor);
924 if (m_pPainter)
925 m_pPainter->SetTextLineColor(_rColor);
928 namespace
930 void lcl_implAlign( vcl::Window* _pWindow, WinBits _nAlignmentBit )
932 WinBits nStyle = _pWindow->GetStyle();
933 nStyle &= ~(WB_LEFT | WB_RIGHT | WB_CENTER);
934 _pWindow->SetStyle( nStyle | _nAlignmentBit );
939 void DbCellControl::AlignControl(sal_Int16 nAlignment)
941 WinBits nAlignmentBit = 0;
942 switch (nAlignment)
944 case css::awt::TextAlign::RIGHT:
945 nAlignmentBit = WB_RIGHT;
946 break;
947 case css::awt::TextAlign::CENTER:
948 nAlignmentBit = WB_CENTER;
949 break;
950 default:
951 nAlignmentBit = WB_LEFT;
952 break;
954 lcl_implAlign( m_pWindow, nAlignmentBit );
955 if ( m_pPainter )
956 lcl_implAlign( m_pPainter, nAlignmentBit );
960 void DbCellControl::PaintCell( OutputDevice& _rDev, const tools::Rectangle& _rRect )
962 if ( m_pPainter->GetParent() == &_rDev )
964 m_pPainter->SetPaintTransparent( true );
965 m_pPainter->SetBackground( );
966 m_pPainter->SetControlBackground( _rDev.GetFillColor() );
967 m_pPainter->SetControlForeground( _rDev.GetTextColor() );
968 m_pPainter->SetTextColor( _rDev.GetTextColor() );
969 m_pPainter->SetTextFillColor( _rDev.GetTextColor() );
971 vcl::Font aFont( _rDev.GetFont() );
972 aFont.SetTransparent( true );
973 m_pPainter->SetFont( aFont );
975 m_pPainter->SetPosSizePixel( _rRect.TopLeft(), _rRect.GetSize() );
976 m_pPainter->Show();
977 m_pPainter->Update();
978 m_pPainter->SetParentUpdateMode( false );
979 m_pPainter->Hide();
980 m_pPainter->SetParentUpdateMode( true );
982 else
983 m_pPainter->Draw( &_rDev, _rRect.TopLeft(), _rRect.GetSize(), DrawFlags::NONE );
987 void DbCellControl::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
989 m_pPainter->SetText( GetFormatText( _rxField, _rxFormatter ) );
990 PaintCell( _rDev, _rRect );
994 double DbCellControl::GetValue(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) const
996 double fValue = 0;
997 if (m_rColumn.IsNumeric())
1001 fValue = _rxField->getDouble();
1003 catch(const Exception&) { }
1005 else
1007 bool bSuccess = false;
1010 fValue = _rxField->getDouble();
1011 bSuccess = true;
1013 catch(const Exception&) { }
1014 if (!bSuccess)
1018 fValue = xFormatter->convertStringToNumber(m_rColumn.GetKey(), _rxField->getString());
1020 catch(const Exception&) { }
1023 return fValue;
1027 void DbCellControl::invalidatedController()
1029 m_rColumn.GetParent().refreshController(m_rColumn.GetId(), DbGridControl::GrantControlAccess());
1032 // CellModels
1034 DbLimitedLengthField::DbLimitedLengthField( DbGridColumn& _rColumn )
1035 :DbCellControl( _rColumn )
1037 doPropertyListening( FM_PROP_MAXTEXTLEN );
1041 void DbLimitedLengthField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1043 DBG_ASSERT( m_pWindow, "DbLimitedLengthField::implAdjustGenericFieldSetting: not to be called without window!" );
1044 DBG_ASSERT( _rxModel.is(), "DbLimitedLengthField::implAdjustGenericFieldSetting: invalid model!" );
1045 if ( m_pWindow && _rxModel.is() )
1047 sal_Int16 nMaxLen = 0;
1048 _rxModel->getPropertyValue( FM_PROP_MAXTEXTLEN ) >>= nMaxLen;
1049 implSetMaxTextLen( nMaxLen );
1053 void DbLimitedLengthField::implSetEffectiveMaxTextLen( sal_Int32 _nMaxLen )
1055 dynamic_cast<Edit&>(*m_pWindow).SetMaxTextLen(_nMaxLen);
1056 if (m_pPainter)
1057 dynamic_cast<Edit&>(*m_pPainter).SetMaxTextLen(_nMaxLen);
1060 DbTextField::DbTextField(DbGridColumn& _rColumn)
1061 :DbLimitedLengthField(_rColumn)
1062 ,m_bIsSimpleEdit( true )
1067 DbTextField::~DbTextField( )
1069 m_pPainterImplementation.reset();
1070 m_pEdit.reset();
1074 void DbTextField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
1076 sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1);
1078 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1080 WinBits nStyle = WB_LEFT;
1081 switch (nAlignment)
1083 case awt::TextAlign::RIGHT:
1084 nStyle = WB_RIGHT;
1085 break;
1087 case awt::TextAlign::CENTER:
1088 nStyle = WB_CENTER;
1089 break;
1092 // is this a multi-line field?
1093 bool bIsMultiLine = false;
1096 if ( xModel.is() )
1098 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MULTILINE ) >>= bIsMultiLine );
1101 catch( const Exception& )
1103 DBG_UNHANDLED_EXCEPTION("svx");
1104 OSL_FAIL( "DbTextField::Init: caught an exception while determining the multi-line capabilities!" );
1107 m_bIsSimpleEdit = !bIsMultiLine;
1108 if ( bIsMultiLine )
1110 m_pWindow = VclPtr<MultiLineTextCell>::Create( &rParent, nStyle );
1111 m_pEdit.reset(new MultiLineEditImplementation( *static_cast< MultiLineTextCell* >( m_pWindow.get() ) ));
1113 m_pPainter = VclPtr<MultiLineTextCell>::Create( &rParent, nStyle );
1114 m_pPainterImplementation.reset(new MultiLineEditImplementation( *static_cast< MultiLineTextCell* >( m_pPainter.get() ) ));
1116 else
1118 m_pWindow = VclPtr<Edit>::Create( &rParent, nStyle );
1119 m_pEdit.reset(new EditImplementation( *static_cast< Edit* >( m_pWindow.get() ) ));
1121 m_pPainter = VclPtr<Edit>::Create( &rParent, nStyle );
1122 m_pPainterImplementation.reset(new EditImplementation( *static_cast< Edit* >( m_pPainter.get() ) ));
1125 if ( WB_LEFT == nStyle )
1127 // this is so that when getting the focus, the selection is oriented left-to-right
1128 AllSettings aSettings = m_pWindow->GetSettings();
1129 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1130 aStyleSettings.SetSelectionOptions(
1131 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
1132 aSettings.SetStyleSettings(aStyleSettings);
1133 m_pWindow->SetSettings(aSettings);
1136 implAdjustGenericFieldSetting( xModel );
1138 DbLimitedLengthField::Init( rParent, xCursor );
1142 CellControllerRef DbTextField::CreateController() const
1144 return new EditCellController( m_pEdit.get() );
1148 void DbTextField::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1150 if ( m_pPainterImplementation )
1151 m_pPainterImplementation->SetText( GetFormatText( _rxField, _rxFormatter ) );
1153 DbLimitedLengthField::PaintFieldToCell( _rDev, _rRect, _rxField, _rxFormatter );
1157 OUString DbTextField::GetFormatText(const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, Color** /*ppColor*/)
1159 if (!_rxField.is())
1160 return OUString();
1162 const css::uno::Reference<css::beans::XPropertySet> xPS(_rxField, UNO_QUERY);
1163 FormattedColumnValue fmter( xFormatter, xPS );
1167 return fmter.getFormattedValue();
1169 catch( const Exception& )
1171 DBG_UNHANDLED_EXCEPTION("svx");
1173 return OUString();
1178 void DbTextField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
1180 m_pEdit->SetText( GetFormatText( _rxField, xFormatter ) );
1181 m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1185 void DbTextField::updateFromModel( Reference< XPropertySet > _rxModel )
1187 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTextField::updateFromModel: invalid call!" );
1189 OUString sText;
1190 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
1192 sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen();
1193 if ( EDIT_NOLIMIT != nMaxTextLen && sText.getLength() > nMaxTextLen )
1195 sal_Int32 nDiff = sText.getLength() - nMaxTextLen;
1196 sText = sText.replaceAt(sText.getLength() - nDiff,nDiff, OUString());
1200 m_pEdit->SetText( sText );
1201 m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1205 bool DbTextField::commitControl()
1207 OUString aText( m_pEdit->GetText( getModelLineEndSetting( m_rColumn.getModel() ) ) );
1208 // we have to check if the length before we can decide if the value was modified
1209 sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen();
1210 if ( EDIT_NOLIMIT != nMaxTextLen )
1212 OUString sOldValue;
1213 m_rColumn.getModel()->getPropertyValue( FM_PROP_TEXT ) >>= sOldValue;
1214 // if the new value didn't change we must set the old long value again
1215 if ( sOldValue.getLength() > nMaxTextLen && sOldValue.compareTo(aText,nMaxTextLen) == 0 )
1216 aText = sOldValue;
1218 m_rColumn.getModel()->setPropertyValue( FM_PROP_TEXT, makeAny( aText ) );
1219 return true;
1223 void DbTextField::implSetEffectiveMaxTextLen( sal_Int32 _nMaxLen )
1225 if ( m_pEdit )
1226 m_pEdit->SetMaxTextLen( _nMaxLen );
1227 if ( m_pPainterImplementation )
1228 m_pPainterImplementation->SetMaxTextLen( _nMaxLen );
1231 DbFormattedField::DbFormattedField(DbGridColumn& _rColumn)
1232 :DbLimitedLengthField(_rColumn)
1234 // if our model's format key changes we want to propagate the new value to our windows
1235 doPropertyListening( FM_PROP_FORMATKEY );
1239 DbFormattedField::~DbFormattedField()
1244 void DbFormattedField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
1246 sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1);
1248 Reference< css::beans::XPropertySet > xUnoModel = m_rColumn.getModel();
1250 switch (nAlignment)
1252 case css::awt::TextAlign::RIGHT:
1253 m_pWindow = VclPtr<FormattedField>::Create( &rParent, WB_RIGHT );
1254 m_pPainter = VclPtr<FormattedField>::Create( &rParent, WB_RIGHT );
1255 break;
1257 case css::awt::TextAlign::CENTER:
1258 m_pWindow = VclPtr<FormattedField>::Create( &rParent, WB_CENTER );
1259 m_pPainter = VclPtr<FormattedField>::Create( &rParent, WB_CENTER );
1260 break;
1261 default:
1262 m_pWindow = VclPtr<FormattedField>::Create( &rParent, WB_LEFT );
1263 m_pPainter = VclPtr<FormattedField>::Create( &rParent, WB_LEFT );
1265 // Everything just so that the selection goes from right to left when getting focus
1266 AllSettings aSettings = m_pWindow->GetSettings();
1267 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1268 aStyleSettings.SetSelectionOptions(
1269 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
1270 aSettings.SetStyleSettings(aStyleSettings);
1271 m_pWindow->SetSettings(aSettings);
1274 implAdjustGenericFieldSetting( xUnoModel );
1276 static_cast< FormattedField* >( m_pWindow.get() )->SetStrictFormat( false );
1277 static_cast< FormattedField* >( m_pPainter.get() )->SetStrictFormat( false );
1278 // if one allows any formatting, one cannot make an entry check anyway
1279 // (the FormattedField does not support that anyway, only derived classes)
1281 // get the formatter from the uno model
1282 // (I could theoretically also go via the css::util::NumberFormatter, which the cursor would
1283 // surely give me. The problem is that I can not really rely on the fact that the two
1284 // formatters are the same. Clean is the whole thing if I go via the UNO model.)
1285 sal_Int32 nFormatKey = -1;
1287 // let's see if the model has one ...
1288 DBG_ASSERT(::comphelper::hasProperty(FM_PROP_FORMATSSUPPLIER, xUnoModel), "DbFormattedField::Init : invalid UNO model !");
1289 Any aSupplier( xUnoModel->getPropertyValue(FM_PROP_FORMATSSUPPLIER));
1290 if (aSupplier.hasValue())
1292 m_xSupplier.set(aSupplier, css::uno::UNO_QUERY);
1293 if (m_xSupplier.is())
1295 // if we take the supplier from the model, then also the key
1296 Any aFmtKey( xUnoModel->getPropertyValue(FM_PROP_FORMATKEY));
1297 if (aFmtKey.hasValue())
1299 DBG_ASSERT(aFmtKey.getValueType().getTypeClass() == TypeClass_LONG, "DbFormattedField::Init : invalid format key property (no sal_Int32) !");
1300 nFormatKey = ::comphelper::getINT32(aFmtKey);
1302 else
1304 SAL_INFO("svx.fmcomp", "DbFormattedField::Init : my uno-model has no format-key, but a formats supplier !");
1305 // the OFormattedModel which we usually are working with ensures that the model has a format key
1306 // as soon as the form is loaded. Unfortunally this method here is called from within loaded, too.
1307 // So if our LoadListener is called before the LoadListener of the model, this "else case" is
1308 // allowed.
1309 // Of course our property listener for the FormatKey property will notify us if the prop is changed,
1310 // so this here isn't really bad...
1311 nFormatKey = 0;
1316 // No? Maybe the css::form::component::Form behind the cursor?
1317 if (!m_xSupplier.is())
1319 if (xCursor.is())
1320 { // If we take the formatter from the cursor, then also the key from the field to which we are bound
1321 m_xSupplier = getNumberFormats(getConnection(xCursor));
1323 if (m_rColumn.GetField().is())
1324 nFormatKey = ::comphelper::getINT32(m_rColumn.GetField()->getPropertyValue(FM_PROP_FORMATKEY));
1328 SvNumberFormatter* pFormatterUsed = nullptr;
1329 if (m_xSupplier.is())
1331 SvNumberFormatsSupplierObj* pImplmentation = comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>(m_xSupplier);
1332 if (pImplmentation)
1333 pFormatterUsed = pImplmentation->GetNumberFormatter();
1334 else
1335 // Everything is invalid: the supplier is of the wrong type, then we can not
1336 // rely on a standard formatter to know the (possibly non-standard) key.
1337 nFormatKey = -1;
1340 // a standard formatter ...
1341 if (pFormatterUsed == nullptr)
1343 pFormatterUsed = static_cast<FormattedField*>(m_pWindow.get())->StandardFormatter();
1344 DBG_ASSERT(pFormatterUsed != nullptr, "DbFormattedField::Init : no standard formatter given by the numeric field !");
1346 // ... and a standard key
1347 if (nFormatKey == -1)
1348 nFormatKey = 0;
1350 static_cast<FormattedField*>(m_pWindow.get())->SetFormatter(pFormatterUsed);
1351 static_cast<FormattedField*>(m_pPainter.get())->SetFormatter(pFormatterUsed);
1353 static_cast<FormattedField*>(m_pWindow.get())->SetFormatKey(nFormatKey);
1354 static_cast<FormattedField*>(m_pPainter.get())->SetFormatKey(nFormatKey);
1356 static_cast<FormattedField*>(m_pWindow.get())->TreatAsNumber(m_rColumn.IsNumeric());
1357 static_cast<FormattedField*>(m_pPainter.get())->TreatAsNumber(m_rColumn.IsNumeric());
1359 // min and max values
1360 if (m_rColumn.IsNumeric())
1362 bool bClearMin = true;
1363 if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MIN, xUnoModel))
1365 Any aMin( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MIN));
1366 if (aMin.getValueType().getTypeClass() != TypeClass_VOID)
1368 DBG_ASSERT(aMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid min value !");
1369 double dMin = ::comphelper::getDouble(aMin);
1370 static_cast<FormattedField*>(m_pWindow.get())->SetMinValue(dMin);
1371 static_cast<FormattedField*>(m_pPainter.get())->SetMinValue(dMin);
1372 bClearMin = false;
1375 if (bClearMin)
1377 static_cast<FormattedField*>(m_pWindow.get())->ClearMinValue();
1378 static_cast<FormattedField*>(m_pPainter.get())->ClearMinValue();
1380 bool bClearMax = true;
1381 if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MAX, xUnoModel))
1383 Any aMin( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MAX));
1384 if (aMin.getValueType().getTypeClass() != TypeClass_VOID)
1386 DBG_ASSERT(aMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid max value !");
1387 double dMin = ::comphelper::getDouble(aMin);
1388 static_cast<FormattedField*>(m_pWindow.get())->SetMaxValue(dMin);
1389 static_cast<FormattedField*>(m_pPainter.get())->SetMaxValue(dMin);
1390 bClearMax = false;
1393 if (bClearMax)
1395 static_cast<FormattedField*>(m_pWindow.get())->ClearMaxValue();
1396 static_cast<FormattedField*>(m_pPainter.get())->ClearMaxValue();
1400 // the default value
1401 Any aDefault( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_DEFAULT));
1402 if (aDefault.hasValue())
1403 { // the thing can be a double or a string
1404 switch (aDefault.getValueType().getTypeClass())
1406 case TypeClass_DOUBLE:
1407 if (m_rColumn.IsNumeric())
1409 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultValue(::comphelper::getDouble(aDefault));
1410 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultValue(::comphelper::getDouble(aDefault));
1412 else
1414 OUString sConverted;
1415 Color* pDummy;
1416 pFormatterUsed->GetOutputString(::comphelper::getDouble(aDefault), 0, sConverted, &pDummy);
1417 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultText(sConverted);
1418 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultText(sConverted);
1420 break;
1421 case TypeClass_STRING:
1423 OUString sDefault( ::comphelper::getString(aDefault) );
1424 if (m_rColumn.IsNumeric())
1426 double dVal;
1427 sal_uInt32 nTestFormat(0);
1428 if (pFormatterUsed->IsNumberFormat(sDefault, nTestFormat, dVal))
1430 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultValue(dVal);
1431 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultValue(dVal);
1434 else
1436 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultText(sDefault);
1437 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultText(sDefault);
1440 break;
1441 default:
1442 OSL_FAIL( "DbFormattedField::Init: unexpected value type!" );
1443 break;
1446 DbLimitedLengthField::Init( rParent, xCursor );
1450 CellControllerRef DbFormattedField::CreateController() const
1452 return new ::svt::FormattedFieldCellController( static_cast< FormattedField* >( m_pWindow.get() ) );
1456 void DbFormattedField::_propertyChanged( const PropertyChangeEvent& _rEvent )
1458 if (_rEvent.PropertyName == FM_PROP_FORMATKEY )
1460 sal_Int32 nNewKey = _rEvent.NewValue.hasValue() ? ::comphelper::getINT32(_rEvent.NewValue) : 0;
1462 DBG_ASSERT(m_pWindow && m_pPainter, "DbFormattedField::_propertyChanged : where are my windows ?");
1463 if (m_pWindow)
1464 static_cast< FormattedField* >( m_pWindow.get() )->SetFormatKey( nNewKey );
1465 if (m_pPainter)
1466 static_cast< FormattedField* >( m_pPainter.get() )->SetFormatKey( nNewKey );
1468 else
1470 DbLimitedLengthField::_propertyChanged( _rEvent );
1475 OUString DbFormattedField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, Color** ppColor)
1477 // no color specification by default
1478 if (ppColor != nullptr)
1479 *ppColor = nullptr;
1481 // NULL value -> empty text
1482 if (!_rxField.is())
1483 return OUString();
1485 OUString aText;
1488 if (m_rColumn.IsNumeric())
1490 // The IsNumeric at the column says nothing about the class of the used format, but
1491 // about the class of the field bound to the column. So when you bind a FormattedField
1492 // column to a double field and format it as text, m_rColumn.IsNumeric() returns
1493 // sal_True. So that simply means that I can query the contents of the variant using
1494 // getDouble, and then I can leave the rest (the formatting) to the FormattedField.
1495 double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() );
1496 if (_rxField->wasNull())
1497 return aText;
1498 static_cast<FormattedField*>(m_pPainter.get())->SetValue(dValue);
1500 else
1502 // Here I can not work with a double, since the field can not provide it to me.
1503 // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form.
1504 aText = _rxField->getString();
1505 if (_rxField->wasNull())
1506 return aText;
1507 static_cast<FormattedField*>(m_pPainter.get())->SetTextFormatted(aText);
1510 catch( const Exception& )
1512 DBG_UNHANDLED_EXCEPTION("svx");
1515 aText = m_pPainter->GetText();
1516 if (ppColor != nullptr)
1517 *ppColor = static_cast<FormattedField*>(m_pPainter.get())->GetLastOutputColor();
1519 return aText;
1523 void DbFormattedField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
1527 FormattedField* pFormattedWindow = static_cast<FormattedField*>(m_pWindow.get());
1528 if (!_rxField.is())
1529 { // NULL value -> empty text
1530 m_pWindow->SetText(OUString());
1532 else if (m_rColumn.IsNumeric())
1534 // The IsNumeric at the column says nothing about the class of the used format, but
1535 // about the class of the field bound to the column. So when you bind a FormattedField
1536 // column to a double field and format it as text, m_rColumn.IsNumeric() returns
1537 // sal_True. So that simply means that I can query the contents of the variant using
1538 // getDouble, and then I can leave the rest (the formatting) to the FormattedField.
1539 double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() );
1540 if (_rxField->wasNull())
1541 m_pWindow->SetText(OUString());
1542 else
1543 pFormattedWindow->SetValue(dValue);
1545 else
1547 // Here I can not work with a double, since the field can not provide it to me.
1548 // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form.
1549 OUString sText( _rxField->getString());
1551 pFormattedWindow->SetTextFormatted( sText );
1552 pFormattedWindow->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1555 catch( const Exception& )
1557 DBG_UNHANDLED_EXCEPTION("svx");
1562 void DbFormattedField::updateFromModel( Reference< XPropertySet > _rxModel )
1564 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFormattedField::updateFromModel: invalid call!" );
1566 FormattedField* pFormattedWindow = static_cast< FormattedField* >( m_pWindow.get() );
1568 OUString sText;
1569 Any aValue = _rxModel->getPropertyValue( FM_PROP_EFFECTIVE_VALUE );
1570 if ( !aValue.hasValue() || (aValue >>= sText) )
1571 { // our effective value is transferred as string
1572 pFormattedWindow->SetTextFormatted( sText );
1573 pFormattedWindow->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1575 else
1577 double dValue = 0;
1578 aValue >>= dValue;
1579 pFormattedWindow->SetValue(dValue);
1584 bool DbFormattedField::commitControl()
1586 Any aNewVal;
1587 FormattedField& rField = *static_cast<FormattedField*>(m_pWindow.get());
1588 DBG_ASSERT(&rField == m_pWindow, "DbFormattedField::commitControl : can't work with a window other than my own !");
1589 if (m_rColumn.IsNumeric())
1591 if (!rField.GetText().isEmpty())
1592 aNewVal <<= rField.GetValue();
1593 // an empty string is passed on as void by default, to start with
1595 else
1596 aNewVal <<= rField.GetTextValue();
1598 m_rColumn.getModel()->setPropertyValue(FM_PROP_EFFECTIVE_VALUE, aNewVal);
1599 return true;
1602 DbCheckBox::DbCheckBox( DbGridColumn& _rColumn )
1603 :DbCellControl( _rColumn )
1605 setAlignedController( false );
1608 namespace
1610 void setCheckBoxStyle( vcl::Window* _pWindow, bool bMono )
1612 AllSettings aSettings = _pWindow->GetSettings();
1613 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1614 if( bMono )
1615 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::Mono );
1616 else
1617 aStyleSettings.SetOptions( aStyleSettings.GetOptions() & (~StyleSettingsOptions::Mono) );
1618 aSettings.SetStyleSettings( aStyleSettings );
1619 _pWindow->SetSettings( aSettings );
1624 void DbCheckBox::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor )
1626 setTransparent( true );
1628 m_pWindow = VclPtr<CheckBoxControl>::Create( &rParent );
1629 m_pPainter = VclPtr<CheckBoxControl>::Create( &rParent );
1631 m_pWindow->SetPaintTransparent( true );
1632 m_pPainter->SetPaintTransparent( true );
1634 m_pPainter->SetBackground();
1638 Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW );
1640 sal_Int16 nStyle = awt::VisualEffect::LOOK3D;
1641 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_VISUALEFFECT ) >>= nStyle );
1643 setCheckBoxStyle( m_pWindow, nStyle == awt::VisualEffect::FLAT );
1644 setCheckBoxStyle( m_pPainter, nStyle == awt::VisualEffect::FLAT );
1646 bool bTristate = true;
1647 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_TRISTATE ) >>= bTristate );
1648 static_cast< CheckBoxControl* >( m_pWindow.get() )->GetBox().EnableTriState( bTristate );
1649 static_cast< CheckBoxControl* >( m_pPainter.get() )->GetBox().EnableTriState( bTristate );
1651 catch( const Exception& )
1653 DBG_UNHANDLED_EXCEPTION("svx");
1656 DbCellControl::Init( rParent, xCursor );
1660 CellControllerRef DbCheckBox::CreateController() const
1662 return new CheckBoxCellController(static_cast<CheckBoxControl*>(m_pWindow.get()));
1665 static void lcl_setCheckBoxState( const Reference< css::sdb::XColumn >& _rxField,
1666 CheckBoxControl* _pCheckBoxControl )
1668 TriState eState = TRISTATE_INDET;
1669 if (_rxField.is())
1673 bool bValue = _rxField->getBoolean();
1674 if (!_rxField->wasNull())
1675 eState = bValue ? TRISTATE_TRUE : TRISTATE_FALSE;
1677 catch( const Exception& )
1679 DBG_UNHANDLED_EXCEPTION("svx");
1682 _pCheckBoxControl->GetBox().SetState(eState);
1686 void DbCheckBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
1688 lcl_setCheckBoxState( _rxField, static_cast<CheckBoxControl*>(m_pWindow.get()) );
1692 void DbCheckBox::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect,
1693 const Reference< css::sdb::XColumn >& _rxField,
1694 const Reference< XNumberFormatter >& xFormatter)
1696 lcl_setCheckBoxState( _rxField, static_cast<CheckBoxControl*>(m_pPainter.get()) );
1697 DbCellControl::PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
1701 void DbCheckBox::updateFromModel( Reference< XPropertySet > _rxModel )
1703 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCheckBox::updateFromModel: invalid call!" );
1705 sal_Int16 nState = TRISTATE_INDET;
1706 _rxModel->getPropertyValue( FM_PROP_STATE ) >>= nState;
1707 static_cast< CheckBoxControl* >( m_pWindow.get() )->GetBox().SetState( static_cast< TriState >( nState ) );
1711 bool DbCheckBox::commitControl()
1713 m_rColumn.getModel()->setPropertyValue( FM_PROP_STATE,
1714 makeAny( static_cast<sal_Int16>( static_cast< CheckBoxControl* >( m_pWindow.get() )->GetBox().GetState() ) ) );
1715 return true;
1719 OUString DbCheckBox::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
1721 return OUString();
1724 DbPatternField::DbPatternField( DbGridColumn& _rColumn, const Reference<XComponentContext>& _rContext )
1725 :DbCellControl( _rColumn )
1726 ,m_xContext( _rContext )
1728 doPropertyListening( FM_PROP_LITERALMASK );
1729 doPropertyListening( FM_PROP_EDITMASK );
1730 doPropertyListening( FM_PROP_STRICTFORMAT );
1734 void DbPatternField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1736 DBG_ASSERT( m_pWindow, "DbPatternField::implAdjustGenericFieldSetting: not to be called without window!" );
1737 DBG_ASSERT( _rxModel.is(), "DbPatternField::implAdjustGenericFieldSetting: invalid model!" );
1738 if ( !m_pWindow || !_rxModel.is() )
1739 return;
1741 OUString aLitMask;
1742 OUString aEditMask;
1743 bool bStrict = false;
1745 _rxModel->getPropertyValue( FM_PROP_LITERALMASK ) >>= aLitMask;
1746 _rxModel->getPropertyValue( FM_PROP_EDITMASK ) >>= aEditMask;
1747 _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) >>= bStrict;
1749 OString aAsciiEditMask(OUStringToOString(aEditMask, RTL_TEXTENCODING_ASCII_US));
1751 static_cast< PatternField* >( m_pWindow.get() )->SetMask( aAsciiEditMask, aLitMask );
1752 static_cast< PatternField* >( m_pPainter.get() )->SetMask( aAsciiEditMask, aLitMask );
1753 static_cast< PatternField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
1754 static_cast< PatternField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
1758 void DbPatternField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
1760 m_rColumn.SetAlignmentFromModel(-1);
1762 m_pWindow = VclPtr<PatternField>::Create( &rParent, 0 );
1763 m_pPainter= VclPtr<PatternField>::Create( &rParent, 0 );
1765 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1766 implAdjustGenericFieldSetting( xModel );
1768 DbCellControl::Init( rParent, xCursor );
1772 CellControllerRef DbPatternField::CreateController() const
1774 return new SpinCellController( static_cast< PatternField* >( m_pWindow.get() ) );
1778 OUString DbPatternField::impl_formatText( const OUString& _rText )
1780 m_pPainter->SetText( _rText );
1781 static_cast< PatternField* >( m_pPainter.get() )->ReformatAll();
1782 return m_pPainter->GetText();
1786 OUString DbPatternField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
1788 bool bIsForPaint = _rxField != m_rColumn.GetField();
1789 ::std::unique_ptr< FormattedColumnValue >& rpFormatter = bIsForPaint ? m_pPaintFormatter : m_pValueFormatter;
1791 if (!rpFormatter)
1793 rpFormatter = std::make_unique< FormattedColumnValue> (
1794 m_xContext, getCursor(), Reference< XPropertySet >( _rxField, UNO_QUERY ) );
1795 OSL_ENSURE(rpFormatter, "DbPatternField::Init: no value formatter!");
1797 else
1798 OSL_ENSURE( rpFormatter->getColumn() == _rxField, "DbPatternField::GetFormatText: my value formatter is working for another field ...!" );
1799 // re-creating the value formatter here every time would be quite expensive ...
1801 OUString sText;
1802 if (rpFormatter)
1803 sText = rpFormatter->getFormattedValue();
1805 return impl_formatText( sText );
1809 void DbPatternField::UpdateFromField( const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1811 static_cast< Edit* >( m_pWindow.get() )->SetText( GetFormatText( _rxField, _rxFormatter ) );
1812 static_cast< Edit* >( m_pWindow.get() )->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1816 void DbPatternField::updateFromModel( Reference< XPropertySet > _rxModel )
1818 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbPatternField::updateFromModel: invalid call!" );
1820 OUString sText;
1821 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
1823 static_cast< Edit* >( m_pWindow.get() )->SetText( impl_formatText( sText ) );
1824 static_cast< Edit* >( m_pWindow.get() )->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1828 bool DbPatternField::commitControl()
1830 OUString aText(m_pWindow->GetText());
1831 m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, makeAny(aText));
1832 return true;
1835 DbSpinField::DbSpinField( DbGridColumn& _rColumn, sal_Int16 _nStandardAlign )
1836 :DbCellControl( _rColumn )
1837 ,m_nStandardAlign( _nStandardAlign )
1842 void DbSpinField::Init( vcl::Window& _rParent, const Reference< XRowSet >& _rxCursor )
1844 m_rColumn.SetAlignmentFromModel( m_nStandardAlign );
1846 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1848 // determine the WinBits for the field
1849 WinBits nFieldStyle = 0;
1850 if ( ::comphelper::getBOOL( xModel->getPropertyValue( FM_PROP_SPIN ) ) )
1851 nFieldStyle = WB_REPEAT | WB_SPIN;
1852 // create the fields
1853 m_pWindow = createField( &_rParent, nFieldStyle, xModel );
1854 m_pPainter = createField( &_rParent, nFieldStyle, xModel );
1856 // adjust all other settings which depend on the property values
1857 implAdjustGenericFieldSetting( xModel );
1859 // call the base class
1860 DbCellControl::Init( _rParent, _rxCursor );
1864 CellControllerRef DbSpinField::CreateController() const
1866 return new SpinCellController( static_cast< SpinField* >( m_pWindow.get() ) );
1869 DbNumericField::DbNumericField( DbGridColumn& _rColumn )
1870 :DbSpinField( _rColumn )
1872 doPropertyListening( FM_PROP_DECIMAL_ACCURACY );
1873 doPropertyListening( FM_PROP_VALUEMIN );
1874 doPropertyListening( FM_PROP_VALUEMAX );
1875 doPropertyListening( FM_PROP_VALUESTEP );
1876 doPropertyListening( FM_PROP_STRICTFORMAT );
1877 doPropertyListening( FM_PROP_SHOWTHOUSANDSEP );
1881 void DbNumericField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1883 DBG_ASSERT( m_pWindow, "DbNumericField::implAdjustGenericFieldSetting: not to be called without window!" );
1884 DBG_ASSERT( _rxModel.is(), "DbNumericField::implAdjustGenericFieldSetting: invalid model!" );
1885 if ( !m_pWindow || !_rxModel.is() )
1886 return;
1888 sal_Int32 nMin = static_cast<sal_Int32>(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) ));
1889 sal_Int32 nMax = static_cast<sal_Int32>(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) ));
1890 sal_Int32 nStep = static_cast<sal_Int32>(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) ));
1891 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
1892 sal_Int16 nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) );
1893 bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) );
1895 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetMinValue(nMin);
1896 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetMaxValue(nMax);
1897 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetSpinSize(nStep);
1898 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetStrictFormat(bStrict);
1900 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetMinValue(nMin);
1901 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetMaxValue(nMax);
1902 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetStrictFormat(bStrict);
1905 // give a formatter to the field and the painter;
1906 // test first if I can get from the service behind a connection
1907 Reference< css::util::XNumberFormatsSupplier > xSupplier;
1908 Reference< XRowSet > xForm;
1909 if ( m_rColumn.GetParent().getDataSource() )
1910 xForm.set( Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY );
1911 if ( xForm.is() )
1912 xSupplier = getNumberFormats( getConnection( xForm ), true );
1913 SvNumberFormatter* pFormatterUsed = nullptr;
1914 if ( xSupplier.is() )
1916 SvNumberFormatsSupplierObj* pImplmentation = comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>( xSupplier );
1917 pFormatterUsed = pImplmentation ? pImplmentation->GetNumberFormatter() : nullptr;
1919 if ( nullptr == pFormatterUsed )
1920 { // the cursor didn't lead to success -> standard
1921 pFormatterUsed = static_cast< DoubleNumericField* >( m_pWindow.get() )->StandardFormatter();
1922 DBG_ASSERT( pFormatterUsed != nullptr, "DbNumericField::implAdjustGenericFieldSetting: no standard formatter given by the numeric field !" );
1924 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetFormatter( pFormatterUsed );
1925 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetFormatter( pFormatterUsed );
1927 // and then generate a format which has the desired length after the decimal point, etc.
1928 LanguageType aAppLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType();
1929 OUString sFormatString = pFormatterUsed->GenerateFormat(0, aAppLanguage, bThousand, false, nScale);
1931 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetFormat( sFormatString, aAppLanguage );
1932 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetFormat( sFormatString, aAppLanguage );
1936 VclPtr<SpinField> DbNumericField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& /*_rxModel*/ )
1938 return VclPtr<DoubleNumericField>::Create( _pParent, _nFieldStyle );
1941 namespace
1944 OUString lcl_setFormattedNumeric_nothrow( DoubleNumericField& _rField, const DbCellControl& _rControl,
1945 const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1947 OUString sValue;
1948 if ( _rxField.is() )
1952 double fValue = _rControl.GetValue( _rxField, _rxFormatter );
1953 if ( !_rxField->wasNull() )
1955 _rField.SetValue( fValue );
1956 sValue = _rField.GetText();
1959 catch( const Exception& )
1961 DBG_UNHANDLED_EXCEPTION("svx");
1964 return sValue;
1969 OUString DbNumericField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, Color** /*ppColor*/)
1971 return lcl_setFormattedNumeric_nothrow(dynamic_cast<DoubleNumericField&>(*m_pPainter), *this, _rxField, _rxFormatter);
1975 void DbNumericField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter)
1977 lcl_setFormattedNumeric_nothrow(dynamic_cast<DoubleNumericField&>(*m_pWindow), *this, _rxField, _rxFormatter);
1981 void DbNumericField::updateFromModel( Reference< XPropertySet > _rxModel )
1983 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbNumericField::updateFromModel: invalid call!" );
1985 double dValue = 0;
1986 if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue )
1987 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetValue( dValue );
1988 else
1989 m_pWindow->SetText( OUString() );
1993 bool DbNumericField::commitControl()
1995 OUString aText( m_pWindow->GetText());
1996 Any aVal;
1998 if (!aText.isEmpty()) // not empty
2000 double fValue = static_cast<DoubleNumericField*>(m_pWindow.get())->GetValue();
2001 aVal <<= fValue;
2003 m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal);
2004 return true;
2007 DbCurrencyField::DbCurrencyField(DbGridColumn& _rColumn)
2008 :DbSpinField( _rColumn )
2009 ,m_nScale( 0 )
2011 doPropertyListening( FM_PROP_DECIMAL_ACCURACY );
2012 doPropertyListening( FM_PROP_VALUEMIN );
2013 doPropertyListening( FM_PROP_VALUEMAX );
2014 doPropertyListening( FM_PROP_VALUESTEP );
2015 doPropertyListening( FM_PROP_STRICTFORMAT );
2016 doPropertyListening( FM_PROP_SHOWTHOUSANDSEP );
2017 doPropertyListening( FM_PROP_CURRENCYSYMBOL );
2021 void DbCurrencyField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2023 DBG_ASSERT( m_pWindow, "DbCurrencyField::implAdjustGenericFieldSetting: not to be called without window!" );
2024 DBG_ASSERT( _rxModel.is(), "DbCurrencyField::implAdjustGenericFieldSetting: invalid model!" );
2025 if ( !m_pWindow || !_rxModel.is() )
2026 return;
2028 m_nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) );
2029 double nMin = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) );
2030 double nMax = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) );
2031 double nStep = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) );
2032 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2033 bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) );
2034 OUString aStr( getString( _rxModel->getPropertyValue(FM_PROP_CURRENCYSYMBOL ) ) );
2036 //fdo#42747 the min/max/first/last of vcl NumericFormatters needs to be
2037 //multiplied by the no of decimal places. See also
2038 //VclBuilder::mungeAdjustment
2039 int nMul = rtl_math_pow10Exp(1, m_nScale);
2040 nMin *= nMul;
2041 nMax *= nMul;
2043 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetUseThousandSep( bThousand );
2044 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetDecimalDigits( m_nScale );
2045 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetCurrencySymbol( aStr );
2046 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetFirst( nMin );
2047 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetLast( nMax );
2048 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetMin( nMin );
2049 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetMax( nMax );
2050 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetSpinSize( nStep );
2051 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
2053 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetUseThousandSep( bThousand );
2054 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetDecimalDigits( m_nScale );
2055 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetCurrencySymbol( aStr );
2056 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetFirst( nMin );
2057 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetLast( nMax );
2058 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetMin( nMin );
2059 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetMax( nMax );
2060 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
2064 VclPtr<SpinField> DbCurrencyField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& /*_rxModel*/ )
2066 return VclPtr<LongCurrencyField>::Create( _pParent, _nFieldStyle );
2070 double DbCurrencyField::GetCurrency(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) const
2072 double fValue = GetValue(_rxField, xFormatter);
2073 if (m_nScale)
2075 // SAL_INFO("svx",("double = %.64f ",fValue);
2076 fValue = ::rtl::math::pow10Exp(fValue, m_nScale);
2077 fValue = ::rtl::math::round(fValue);
2079 return fValue;
2082 namespace
2085 OUString lcl_setFormattedCurrency_nothrow( LongCurrencyField& _rField, const DbCurrencyField& _rControl,
2086 const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
2088 OUString sValue;
2089 if ( _rxField.is() )
2093 double fValue = _rControl.GetCurrency( _rxField, _rxFormatter );
2094 if ( !_rxField->wasNull() )
2096 _rField.SetValue( fValue );
2097 sValue = _rField.GetText();
2100 catch( const Exception& )
2102 DBG_UNHANDLED_EXCEPTION("svx");
2105 return sValue;
2110 OUString DbCurrencyField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, Color** /*ppColor*/)
2112 return lcl_setFormattedCurrency_nothrow( dynamic_cast< LongCurrencyField& >( *m_pPainter ), *this, _rxField, _rxFormatter );
2116 void DbCurrencyField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter)
2118 lcl_setFormattedCurrency_nothrow( dynamic_cast< LongCurrencyField& >( *m_pWindow ), *this, _rxField, _rxFormatter );
2122 void DbCurrencyField::updateFromModel( Reference< XPropertySet > _rxModel )
2124 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCurrencyField::updateFromModel: invalid call!" );
2126 double dValue = 0;
2127 if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue )
2129 if ( m_nScale )
2131 dValue = ::rtl::math::pow10Exp( dValue, m_nScale );
2132 dValue = ::rtl::math::round(dValue);
2135 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetValue( dValue );
2137 else
2138 m_pWindow->SetText( OUString() );
2142 bool DbCurrencyField::commitControl()
2144 OUString aText(m_pWindow->GetText());
2145 Any aVal;
2146 if (!aText.isEmpty()) // not empty
2148 double fValue = static_cast<LongCurrencyField*>(m_pWindow.get())->GetValue();
2149 if (m_nScale)
2151 fValue /= ::rtl::math::pow10Exp(1.0, m_nScale);
2153 aVal <<= fValue;
2155 m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal);
2156 return true;
2159 DbDateField::DbDateField( DbGridColumn& _rColumn )
2160 :DbSpinField( _rColumn )
2162 doPropertyListening( FM_PROP_DATEFORMAT );
2163 doPropertyListening( FM_PROP_DATEMIN );
2164 doPropertyListening( FM_PROP_DATEMAX );
2165 doPropertyListening( FM_PROP_STRICTFORMAT );
2166 doPropertyListening( FM_PROP_DATE_SHOW_CENTURY );
2170 VclPtr<SpinField> DbDateField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& _rxModel )
2172 // check if there is a DropDown property set to TRUE
2173 bool bDropDown = !hasProperty( FM_PROP_DROPDOWN, _rxModel )
2174 || getBOOL( _rxModel->getPropertyValue( FM_PROP_DROPDOWN ) );
2175 if ( bDropDown )
2176 _nFieldStyle |= WB_DROPDOWN;
2178 VclPtr<CalendarField> pField = VclPtr<CalendarField>::Create( _pParent, _nFieldStyle );
2180 pField->EnableToday();
2181 pField->EnableNone();
2183 return pField;
2187 void DbDateField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2189 DBG_ASSERT( m_pWindow, "DbDateField::implAdjustGenericFieldSetting: not to be called without window!" );
2190 DBG_ASSERT( _rxModel.is(), "DbDateField::implAdjustGenericFieldSetting: invalid model!" );
2191 if ( !m_pWindow || !_rxModel.is() )
2192 return;
2194 sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_DATEFORMAT ) );
2195 util::Date aMin;
2196 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMIN ) >>= aMin );
2197 util::Date aMax;
2198 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMAX ) >>= aMax );
2199 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2201 Any aCentury = _rxModel->getPropertyValue( FM_PROP_DATE_SHOW_CENTURY );
2202 if ( aCentury.getValueType().getTypeClass() != TypeClass_VOID )
2204 bool bShowDateCentury = getBOOL( aCentury );
2206 static_cast<DateField*>( m_pWindow.get() )->SetShowDateCentury( bShowDateCentury );
2207 static_cast<DateField*>( m_pPainter.get() )->SetShowDateCentury( bShowDateCentury );
2210 static_cast< DateField* >( m_pWindow.get() )->SetExtDateFormat( static_cast<ExtDateFieldFormat>(nFormat) );
2211 static_cast< DateField* >( m_pWindow.get() )->SetMin( aMin );
2212 static_cast< DateField* >( m_pWindow.get() )->SetMax( aMax );
2213 static_cast< DateField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
2214 static_cast< DateField* >( m_pWindow.get() )->EnableEmptyFieldValue( true );
2216 static_cast< DateField* >( m_pPainter.get() )->SetExtDateFormat( static_cast<ExtDateFieldFormat>(nFormat) );
2217 static_cast< DateField* >( m_pPainter.get() )->SetMin( aMin );
2218 static_cast< DateField* >( m_pPainter.get() )->SetMax( aMax );
2219 static_cast< DateField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
2220 static_cast< DateField* >( m_pPainter.get() )->EnableEmptyFieldValue( true );
2223 namespace
2226 OUString lcl_setFormattedDate_nothrow( DateField& _rField, const Reference< XColumn >& _rxField )
2228 OUString sDate;
2229 if ( _rxField.is() )
2233 css::util::Date aValue = _rxField->getDate();
2234 if ( _rxField->wasNull() )
2235 _rField.SetText( sDate );
2236 else
2238 _rField.SetDate( ::Date( aValue.Day, aValue.Month, aValue.Year ) );
2239 sDate = _rField.GetText();
2242 catch( const Exception& )
2244 DBG_UNHANDLED_EXCEPTION("svx");
2247 return sDate;
2251 OUString DbDateField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
2253 return lcl_setFormattedDate_nothrow(dynamic_cast<DateField&>(*m_pPainter.get()), _rxField);
2257 void DbDateField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
2259 lcl_setFormattedDate_nothrow(dynamic_cast<DateField&>(*m_pWindow.get()), _rxField);
2263 void DbDateField::updateFromModel( Reference< XPropertySet > _rxModel )
2265 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbDateField::updateFromModel: invalid call!" );
2267 util::Date aDate;
2268 if ( _rxModel->getPropertyValue( FM_PROP_DATE ) >>= aDate )
2269 static_cast< DateField* >( m_pWindow.get() )->SetDate( ::Date( aDate ) );
2270 else
2271 static_cast< DateField* >( m_pWindow.get() )->SetText( OUString() );
2275 bool DbDateField::commitControl()
2277 OUString aText(m_pWindow->GetText());
2278 Any aVal;
2279 if (!aText.isEmpty())
2280 aVal <<= static_cast<DateField*>(m_pWindow.get())->GetDate().GetUNODate();
2281 else
2282 aVal.clear();
2284 m_rColumn.getModel()->setPropertyValue(FM_PROP_DATE, aVal);
2285 return true;
2288 DbTimeField::DbTimeField( DbGridColumn& _rColumn )
2289 :DbSpinField( _rColumn, css::awt::TextAlign::LEFT )
2291 doPropertyListening( FM_PROP_TIMEFORMAT );
2292 doPropertyListening( FM_PROP_TIMEMIN );
2293 doPropertyListening( FM_PROP_TIMEMAX );
2294 doPropertyListening( FM_PROP_STRICTFORMAT );
2298 VclPtr<SpinField> DbTimeField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& /*_rxModel*/ )
2300 return VclPtr<TimeField>::Create( _pParent, _nFieldStyle );
2304 void DbTimeField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2306 DBG_ASSERT( m_pWindow, "DbTimeField::implAdjustGenericFieldSetting: not to be called without window!" );
2307 DBG_ASSERT( _rxModel.is(), "DbTimeField::implAdjustGenericFieldSetting: invalid model!" );
2308 if ( !m_pWindow || !_rxModel.is() )
2309 return;
2311 sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_TIMEFORMAT ) );
2312 util::Time aMin;
2313 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMIN ) >>= aMin );
2314 util::Time aMax;
2315 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMAX ) >>= aMax );
2316 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2318 static_cast< TimeField* >( m_pWindow.get() )->SetExtFormat( static_cast<ExtTimeFieldFormat>(nFormat) );
2319 static_cast< TimeField* >( m_pWindow.get() )->SetMin( aMin );
2320 static_cast< TimeField* >( m_pWindow.get() )->SetMax( aMax );
2321 static_cast< TimeField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
2322 static_cast< TimeField* >( m_pWindow.get() )->EnableEmptyFieldValue( true );
2324 static_cast< TimeField* >( m_pPainter.get() )->SetExtFormat( static_cast<ExtTimeFieldFormat>(nFormat) );
2325 static_cast< TimeField* >( m_pPainter.get() )->SetMin( aMin );
2326 static_cast< TimeField* >( m_pPainter.get() )->SetMax( aMax );
2327 static_cast< TimeField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
2328 static_cast< TimeField* >( m_pPainter.get() )->EnableEmptyFieldValue( true );
2331 namespace
2334 OUString lcl_setFormattedTime_nothrow( TimeField& _rField, const Reference< XColumn >& _rxField )
2336 OUString sTime;
2337 if ( _rxField.is() )
2341 css::util::Time aValue = _rxField->getTime();
2342 if ( _rxField->wasNull() )
2343 _rField.SetText( sTime );
2344 else
2346 _rField.SetTime( ::tools::Time( aValue ) );
2347 sTime = _rField.GetText();
2350 catch( const Exception& )
2352 DBG_UNHANDLED_EXCEPTION("svx");
2355 return sTime;
2359 OUString DbTimeField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
2361 return lcl_setFormattedTime_nothrow( *static_cast< TimeField* >( m_pPainter.get() ), _rxField );
2365 void DbTimeField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
2367 lcl_setFormattedTime_nothrow( *static_cast< TimeField* >( m_pWindow.get() ), _rxField );
2371 void DbTimeField::updateFromModel( Reference< XPropertySet > _rxModel )
2373 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTimeField::updateFromModel: invalid call!" );
2375 util::Time aTime;
2376 if ( _rxModel->getPropertyValue( FM_PROP_TIME ) >>= aTime )
2377 static_cast< TimeField* >( m_pWindow.get() )->SetTime( ::tools::Time( aTime ) );
2378 else
2379 static_cast< TimeField* >( m_pWindow.get() )->SetText( OUString() );
2383 bool DbTimeField::commitControl()
2385 OUString aText(m_pWindow->GetText());
2386 Any aVal;
2387 if (!aText.isEmpty())
2388 aVal <<= static_cast<TimeField*>(m_pWindow.get())->GetTime().GetUNOTime();
2389 else
2390 aVal.clear();
2392 m_rColumn.getModel()->setPropertyValue(FM_PROP_TIME, aVal);
2393 return true;
2396 DbComboBox::DbComboBox(DbGridColumn& _rColumn)
2397 :DbCellControl(_rColumn)
2399 setAlignedController( false );
2401 doPropertyListening( FM_PROP_STRINGITEMLIST );
2402 doPropertyListening( FM_PROP_LINECOUNT );
2406 void DbComboBox::_propertyChanged( const PropertyChangeEvent& _rEvent )
2408 if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST )
2410 SetList(_rEvent.NewValue);
2412 else
2414 DbCellControl::_propertyChanged( _rEvent ) ;
2419 void DbComboBox::SetList(const Any& rItems)
2421 ComboBoxControl* pField = static_cast<ComboBoxControl*>(m_pWindow.get());
2422 pField->Clear();
2424 css::uno::Sequence<OUString> aTest;
2425 if (rItems >>= aTest)
2427 for (const OUString& rString : std::as_const(aTest))
2428 pField->InsertEntry(rString);
2430 // tell the grid control that this controller is invalid and has to be re-initialized
2431 invalidatedController();
2436 void DbComboBox::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2438 DBG_ASSERT( m_pWindow, "DbComboBox::implAdjustGenericFieldSetting: not to be called without window!" );
2439 DBG_ASSERT( _rxModel.is(), "DbComboBox::implAdjustGenericFieldSetting: invalid model!" );
2440 if ( m_pWindow && _rxModel.is() )
2442 sal_Int16 nLines = getINT16( _rxModel->getPropertyValue( FM_PROP_LINECOUNT ) );
2443 static_cast< ComboBoxControl* >( m_pWindow.get() )->SetDropDownLineCount( nLines );
2448 void DbComboBox::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor )
2450 m_rColumn.SetAlignmentFromModel(css::awt::TextAlign::LEFT);
2452 m_pWindow = VclPtr<ComboBoxControl>::Create( &rParent );
2454 // selection from right to left
2455 AllSettings aSettings = m_pWindow->GetSettings();
2456 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2457 aStyleSettings.SetSelectionOptions(
2458 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2459 aSettings.SetStyleSettings(aStyleSettings);
2460 m_pWindow->SetSettings(aSettings, true);
2462 // some initial properties
2463 Reference< XPropertySet > xModel(m_rColumn.getModel());
2464 SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) );
2465 implAdjustGenericFieldSetting( xModel );
2467 DbCellControl::Init( rParent, xCursor );
2471 CellControllerRef DbComboBox::CreateController() const
2473 return new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2477 OUString DbComboBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, Color** /*ppColor*/)
2479 const css::uno::Reference<css::beans::XPropertySet> xPS(_rxField, UNO_QUERY);
2480 ::dbtools::FormattedColumnValue fmter( xFormatter, xPS );
2482 return fmter.getFormattedValue();
2486 void DbComboBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
2488 m_pWindow->SetText(GetFormatText(_rxField, xFormatter));
2492 void DbComboBox::updateFromModel( Reference< XPropertySet > _rxModel )
2494 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbComboBox::updateFromModel: invalid call!" );
2496 OUString sText;
2497 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
2499 static_cast< ComboBox* >( m_pWindow.get() )->SetText( sText );
2500 static_cast< ComboBox* >( m_pWindow.get() )->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
2504 bool DbComboBox::commitControl()
2506 OUString aText( m_pWindow->GetText());
2507 m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, makeAny(aText));
2508 return true;
2512 DbListBox::DbListBox(DbGridColumn& _rColumn)
2513 :DbCellControl(_rColumn)
2514 ,m_bBound(false)
2516 setAlignedController( false );
2518 doPropertyListening( FM_PROP_STRINGITEMLIST );
2519 doPropertyListening( FM_PROP_LINECOUNT );
2523 void DbListBox::_propertyChanged( const css::beans::PropertyChangeEvent& _rEvent )
2525 if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST )
2527 SetList(_rEvent.NewValue);
2529 else
2531 DbCellControl::_propertyChanged( _rEvent ) ;
2536 void DbListBox::SetList(const Any& rItems)
2538 ListBoxControl* pField = static_cast<ListBoxControl*>(m_pWindow.get());
2540 pField->Clear();
2541 m_bBound = false;
2543 css::uno::Sequence<OUString> aTest;
2544 if (rItems >>= aTest)
2546 if (aTest.hasElements())
2548 for (const OUString& rString : std::as_const(aTest))
2549 pField->InsertEntry(rString);
2551 m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList;
2552 m_bBound = m_aValueList.hasElements();
2554 // tell the grid control that this controller is invalid and has to be re-initialized
2555 invalidatedController();
2561 void DbListBox::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
2563 m_rColumn.SetAlignment(css::awt::TextAlign::LEFT);
2565 m_pWindow = VclPtr<ListBoxControl>::Create( &rParent );
2567 // some initial properties
2568 Reference< XPropertySet > xModel( m_rColumn.getModel() );
2569 SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) );
2570 implAdjustGenericFieldSetting( xModel );
2572 DbCellControl::Init( rParent, xCursor );
2576 void DbListBox::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2578 DBG_ASSERT( m_pWindow, "DbListBox::implAdjustGenericFieldSetting: not to be called without window!" );
2579 DBG_ASSERT( _rxModel.is(), "DbListBox::implAdjustGenericFieldSetting: invalid model!" );
2580 if ( m_pWindow && _rxModel.is() )
2582 sal_Int16 nLines = getINT16( _rxModel->getPropertyValue( FM_PROP_LINECOUNT ) );
2583 static_cast< ListBoxControl* >( m_pWindow.get() )->SetDropDownLineCount( nLines );
2588 CellControllerRef DbListBox::CreateController() const
2590 return new ListBoxCellController(static_cast<ListBoxControl*>(m_pWindow.get()));
2594 OUString DbListBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
2596 OUString sText;
2597 if ( _rxField.is() )
2601 sText = _rxField->getString();
2602 if ( m_bBound )
2604 sal_Int32 nPos = ::comphelper::findValue( m_aValueList, sText );
2605 if ( nPos != -1 )
2606 sText = static_cast<ListBox*>(m_pWindow.get())->GetEntry(nPos);
2607 else
2608 sText.clear();
2611 catch( const Exception& )
2613 DBG_UNHANDLED_EXCEPTION("svx");
2616 return sText;
2620 void DbListBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
2622 OUString sFormattedText( GetFormatText( _rxField, xFormatter ) );
2623 if (!sFormattedText.isEmpty())
2624 static_cast< ListBox* >( m_pWindow.get() )->SelectEntry( sFormattedText );
2625 else
2626 static_cast< ListBox* >( m_pWindow.get() )->SetNoSelection();
2630 void DbListBox::updateFromModel( Reference< XPropertySet > _rxModel )
2632 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbListBox::updateFromModel: invalid call!" );
2634 Sequence< sal_Int16 > aSelection;
2635 _rxModel->getPropertyValue( FM_PROP_SELECT_SEQ ) >>= aSelection;
2637 sal_Int16 nSelection = -1;
2638 if ( aSelection.hasElements() )
2639 nSelection = aSelection[ 0 ];
2641 ListBox* pListBox = static_cast< ListBox* >( m_pWindow.get() );
2643 if ( ( nSelection >= 0 ) && ( nSelection < pListBox->GetEntryCount() ) )
2644 pListBox->SelectEntryPos( nSelection );
2645 else
2646 pListBox->SetNoSelection( );
2650 bool DbListBox::commitControl()
2652 Any aVal;
2653 Sequence<sal_Int16> aSelectSeq;
2654 if (static_cast<ListBox*>(m_pWindow.get())->GetSelectedEntryCount())
2656 aSelectSeq.realloc(1);
2657 *aSelectSeq.getArray() = static_cast<sal_Int16>(static_cast<ListBox*>(m_pWindow.get())->GetSelectedEntryPos());
2659 aVal <<= aSelectSeq;
2660 m_rColumn.getModel()->setPropertyValue(FM_PROP_SELECT_SEQ, aVal);
2661 return true;
2664 DbFilterField::DbFilterField(const Reference< XComponentContext >& rxContext,DbGridColumn& _rColumn)
2665 :DbCellControl(_rColumn)
2666 ,OSQLParserClient(rxContext)
2667 ,m_nControlClass(css::form::FormComponentType::TEXTFIELD)
2668 ,m_bFilterList(false)
2669 ,m_bFilterListFilled(false)
2672 setAlignedController( false );
2676 DbFilterField::~DbFilterField()
2678 if (m_nControlClass == css::form::FormComponentType::CHECKBOX)
2679 static_cast<CheckBoxControl*>(m_pWindow.get())->SetClickHdl( Link<VclPtr<CheckBox>,void>() );
2684 void DbFilterField::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect)
2686 static const DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter | DrawTextFlags::Left;
2687 switch (m_nControlClass)
2689 case FormComponentType::CHECKBOX:
2690 DbCellControl::PaintCell( rDev, rRect );
2691 break;
2692 case FormComponentType::LISTBOX:
2693 rDev.DrawText(rRect, static_cast<ListBox*>(m_pWindow.get())->GetSelectedEntry(), nStyle);
2694 break;
2695 default:
2696 rDev.DrawText(rRect, m_aText, nStyle);
2701 void DbFilterField::SetList(const Any& rItems, bool bComboBox)
2703 css::uno::Sequence<OUString> aTest;
2704 rItems >>= aTest;
2705 if (aTest.hasElements())
2707 if (bComboBox)
2709 ComboBox* pField = static_cast<ComboBox*>(m_pWindow.get());
2710 for (const OUString& rString : std::as_const(aTest))
2711 pField->InsertEntry(rString);
2713 else
2715 ListBox* pField = static_cast<ListBox*>(m_pWindow.get());
2716 for (const OUString& rString : std::as_const(aTest))
2717 pField->InsertEntry(rString);
2719 m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList;
2725 void DbFilterField::CreateControl(vcl::Window* pParent, const Reference< css::beans::XPropertySet >& xModel)
2727 switch (m_nControlClass)
2729 case css::form::FormComponentType::CHECKBOX:
2730 m_pWindow = VclPtr<CheckBoxControl>::Create(pParent);
2731 m_pWindow->SetPaintTransparent( true );
2732 static_cast<CheckBoxControl*>(m_pWindow.get())->SetClickHdl( LINK( this, DbFilterField, OnClick ) );
2734 m_pPainter = VclPtr<CheckBoxControl>::Create(pParent);
2735 m_pPainter->SetPaintTransparent( true );
2736 m_pPainter->SetBackground();
2737 break;
2738 case css::form::FormComponentType::LISTBOX:
2740 m_pWindow = VclPtr<ListBoxControl>::Create(pParent);
2741 sal_Int16 nLines = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_LINECOUNT));
2742 Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST);
2743 SetList(aItems, m_nControlClass == css::form::FormComponentType::COMBOBOX);
2744 static_cast<ListBox*>(m_pWindow.get())->SetDropDownLineCount(nLines);
2745 } break;
2746 case css::form::FormComponentType::COMBOBOX:
2748 m_pWindow = VclPtr<ComboBoxControl>::Create(pParent);
2750 AllSettings aSettings = m_pWindow->GetSettings();
2751 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2752 aStyleSettings.SetSelectionOptions(
2753 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2754 aSettings.SetStyleSettings(aStyleSettings);
2755 m_pWindow->SetSettings(aSettings, true);
2757 if (!m_bFilterList)
2759 sal_Int16 nLines = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_LINECOUNT));
2760 Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST);
2761 SetList(aItems, m_nControlClass == css::form::FormComponentType::COMBOBOX);
2762 static_cast<ComboBox*>(m_pWindow.get())->SetDropDownLineCount(nLines);
2764 else
2765 static_cast<ComboBox*>(m_pWindow.get())->SetDropDownLineCount(5);
2767 } break;
2768 default:
2770 m_pWindow = VclPtr<Edit>::Create(pParent, WB_LEFT);
2771 AllSettings aSettings = m_pWindow->GetSettings();
2772 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2773 aStyleSettings.SetSelectionOptions(
2774 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2775 aSettings.SetStyleSettings(aStyleSettings);
2776 m_pWindow->SetSettings(aSettings, true);
2782 void DbFilterField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor )
2784 Reference< css::beans::XPropertySet > xModel(m_rColumn.getModel());
2785 m_rColumn.SetAlignment(css::awt::TextAlign::LEFT);
2787 if (xModel.is())
2789 m_bFilterList = ::comphelper::hasProperty(FM_PROP_FILTERPROPOSAL, xModel) && ::comphelper::getBOOL(xModel->getPropertyValue(FM_PROP_FILTERPROPOSAL));
2790 if (m_bFilterList)
2791 m_nControlClass = css::form::FormComponentType::COMBOBOX;
2792 else
2794 sal_Int16 nClassId = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_CLASSID));
2795 switch (nClassId)
2797 case FormComponentType::CHECKBOX:
2798 case FormComponentType::LISTBOX:
2799 case FormComponentType::COMBOBOX:
2800 m_nControlClass = nClassId;
2801 break;
2802 default:
2803 if (m_bFilterList)
2804 m_nControlClass = FormComponentType::COMBOBOX;
2805 else
2806 m_nControlClass = FormComponentType::TEXTFIELD;
2811 CreateControl( &rParent, xModel );
2812 DbCellControl::Init( rParent, xCursor );
2814 // filter cells are never readonly
2815 Edit* pAsEdit = dynamic_cast< Edit* >( m_pWindow.get() );
2816 if ( pAsEdit )
2817 pAsEdit->SetReadOnly( false );
2821 CellControllerRef DbFilterField::CreateController() const
2823 CellControllerRef xController;
2824 switch (m_nControlClass)
2826 case css::form::FormComponentType::CHECKBOX:
2827 xController = new CheckBoxCellController(static_cast<CheckBoxControl*>(m_pWindow.get()));
2828 break;
2829 case css::form::FormComponentType::LISTBOX:
2830 xController = new ListBoxCellController(static_cast<ListBoxControl*>(m_pWindow.get()));
2831 break;
2832 case css::form::FormComponentType::COMBOBOX:
2833 xController = new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2834 break;
2835 default:
2836 if (m_bFilterList)
2837 xController = new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2838 else
2839 xController = new EditCellController(static_cast<Edit*>(m_pWindow.get()));
2841 return xController;
2845 void DbFilterField::updateFromModel( Reference< XPropertySet > _rxModel )
2847 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFilterField::updateFromModel: invalid call!" );
2849 OSL_FAIL( "DbListBox::updateFromModel: not implemented yet (how the hell did you reach this?)!" );
2850 // TODO: implement this.
2851 // remember: updateFromModel should be some kind of opposite of commitControl
2855 bool DbFilterField::commitControl()
2857 OUString aText(m_aText);
2858 switch (m_nControlClass)
2860 case css::form::FormComponentType::CHECKBOX:
2861 return true;
2862 case css::form::FormComponentType::LISTBOX:
2863 aText.clear();
2864 if (static_cast<ListBox*>(m_pWindow.get())->GetSelectedEntryCount())
2866 sal_Int16 nPos = static_cast<sal_Int16>(static_cast<ListBox*>(m_pWindow.get())->GetSelectedEntryPos());
2867 if ( ( nPos >= 0 ) && ( nPos < m_aValueList.getLength() ) )
2868 aText = m_aValueList.getConstArray()[nPos];
2871 if (m_aText != aText)
2873 m_aText = aText;
2874 m_aCommitLink.Call(*this);
2876 return true;
2877 default:
2878 aText = m_pWindow->GetText();
2881 if (m_aText != aText)
2883 // check the text with the SQL-Parser
2884 OUString aNewText(comphelper::string::stripEnd(aText, ' '));
2885 if (!aNewText.isEmpty())
2887 OUString aErrorMsg;
2888 Reference< XNumberFormatter > xNumberFormatter(m_rColumn.GetParent().getNumberFormatter());
2890 std::unique_ptr< OSQLParseNode > pParseNode = predicateTree(aErrorMsg, aNewText,xNumberFormatter, m_rColumn.GetField());
2891 if (pParseNode != nullptr)
2893 OUString aPreparedText;
2895 css::lang::Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
2897 Reference< XRowSet > xDataSourceRowSet(
2898 Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY);
2899 Reference< XConnection > xConnection(getConnection(xDataSourceRowSet));
2901 pParseNode->parseNodeToPredicateStr(aPreparedText,
2902 xConnection,
2903 xNumberFormatter,
2904 m_rColumn.GetField(),
2905 OUString(),
2906 aAppLocale,
2907 OUString("."),
2908 getParseContext());
2909 m_aText = aPreparedText;
2911 else
2914 SQLException aError;
2915 aError.Message = aErrorMsg;
2916 displayException(aError, m_pWindow->GetParent());
2917 // TODO: transport the title
2919 return false;
2922 else
2923 m_aText = aText;
2925 m_pWindow->SetText(m_aText);
2926 m_aCommitLink.Call(*this);
2928 return true;
2932 void DbFilterField::SetText(const OUString& rText)
2934 m_aText = rText;
2935 switch (m_nControlClass)
2937 case css::form::FormComponentType::CHECKBOX:
2939 TriState eState;
2940 if (rText == "1")
2941 eState = TRISTATE_TRUE;
2942 else if (rText == "0")
2943 eState = TRISTATE_FALSE;
2944 else
2945 eState = TRISTATE_INDET;
2947 static_cast<CheckBoxControl*>(m_pWindow.get())->GetBox().SetState(eState);
2948 static_cast<CheckBoxControl*>(m_pPainter.get())->GetBox().SetState(eState);
2949 } break;
2950 case css::form::FormComponentType::LISTBOX:
2952 sal_Int32 nPos = ::comphelper::findValue(m_aValueList, m_aText);
2953 if (nPos != -1)
2954 static_cast<ListBox*>(m_pWindow.get())->SelectEntryPos(nPos);
2955 else
2956 static_cast<ListBox*>(m_pWindow.get())->SetNoSelection();
2957 } break;
2958 default:
2959 m_pWindow->SetText(m_aText);
2962 // now force a repaint on the window
2963 m_rColumn.GetParent().RowModified(0);
2967 void DbFilterField::Update()
2969 // should we fill the combobox with a filter proposal?
2970 if (!m_bFilterList || m_bFilterListFilled)
2971 return;
2973 m_bFilterListFilled = true;
2974 Reference< css::beans::XPropertySet > xField = m_rColumn.GetField();
2975 if (!xField.is())
2976 return;
2978 OUString aName;
2979 xField->getPropertyValue(FM_PROP_NAME) >>= aName;
2981 // the columnmodel
2982 Reference< css::container::XChild > xModelAsChild(m_rColumn.getModel(), UNO_QUERY);
2983 // the grid model
2984 xModelAsChild.set(xModelAsChild->getParent(),UNO_QUERY);
2985 Reference< XRowSet > xForm(xModelAsChild->getParent(), UNO_QUERY);
2986 if (!xForm.is())
2987 return;
2989 Reference<XPropertySet> xFormProp(xForm,UNO_QUERY);
2990 Reference< XTablesSupplier > xSupTab;
2991 xFormProp->getPropertyValue("SingleSelectQueryComposer") >>= xSupTab;
2993 Reference< XConnection > xConnection(getConnection(xForm));
2994 if (!xSupTab.is())
2995 return;
2997 // search the field
2998 Reference< XColumnsSupplier > xSupCol(xSupTab,UNO_QUERY);
2999 Reference< css::container::XNameAccess > xFieldNames = xSupCol->getColumns();
3000 if (!xFieldNames->hasByName(aName))
3001 return;
3003 Reference< css::container::XNameAccess > xTablesNames = xSupTab->getTables();
3004 Reference< css::beans::XPropertySet > xComposerFieldAsSet(xFieldNames->getByName(aName),UNO_QUERY);
3006 if (!xComposerFieldAsSet.is() ||
3007 !::comphelper::hasProperty(FM_PROP_TABLENAME, xComposerFieldAsSet) ||
3008 !::comphelper::hasProperty(FM_PROP_FIELDSOURCE, xComposerFieldAsSet))
3009 return;
3011 OUString aFieldName;
3012 OUString aTableName;
3013 xComposerFieldAsSet->getPropertyValue(FM_PROP_FIELDSOURCE) >>= aFieldName;
3014 xComposerFieldAsSet->getPropertyValue(FM_PROP_TABLENAME) >>= aTableName;
3016 // no possibility to create a select statement
3017 // looking for the complete table name
3018 if (!xTablesNames->hasByName(aTableName))
3019 return;
3021 // build a statement and send as query;
3022 // Access to the connection
3023 Reference< XStatement > xStatement;
3024 Reference< XResultSet > xListCursor;
3025 Reference< css::sdb::XColumn > xDataField;
3029 Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData();
3031 OUString aQuote(xMeta->getIdentifierQuoteString());
3032 OUStringBuffer aStatement("SELECT DISTINCT ");
3033 aStatement.append(quoteName(aQuote, aName));
3034 if (!aFieldName.isEmpty() && aName != aFieldName)
3036 aStatement.append(" AS ");
3037 aStatement.append(quoteName(aQuote, aFieldName));
3040 aStatement.append(" FROM ");
3042 Reference< XPropertySet > xTableNameAccess(xTablesNames->getByName(aTableName), UNO_QUERY_THROW);
3043 aStatement.append(composeTableNameForSelect(xConnection, xTableNameAccess));
3045 xStatement = xConnection->createStatement();
3046 Reference< css::beans::XPropertySet > xStatementProps(xStatement, UNO_QUERY);
3047 xStatementProps->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, makeAny(true));
3049 xListCursor = xStatement->executeQuery(aStatement.makeStringAndClear());
3051 Reference< css::sdbcx::XColumnsSupplier > xSupplyCols(xListCursor, UNO_QUERY);
3052 Reference< css::container::XIndexAccess > xFields(xSupplyCols->getColumns(), UNO_QUERY);
3053 xDataField.set(xFields->getByIndex(0), css::uno::UNO_QUERY);
3054 if (!xDataField.is())
3055 return;
3057 catch(const Exception&)
3059 ::comphelper::disposeComponent(xStatement);
3060 return;
3063 sal_Int16 i = 0;
3064 ::std::vector< OUString > aStringList;
3065 aStringList.reserve(16);
3066 OUString aStr;
3067 css::util::Date aNullDate = m_rColumn.GetParent().getNullDate();
3068 sal_Int32 nFormatKey = m_rColumn.GetKey();
3069 Reference< XNumberFormatter > xFormatter = m_rColumn.GetParent().getNumberFormatter();
3070 sal_Int16 nKeyType = ::comphelper::getNumberFormatType(xFormatter->getNumberFormatsSupplier()->getNumberFormats(), nFormatKey);
3072 while (!xListCursor->isAfterLast() && i++ < SHRT_MAX) // max number of entries
3074 aStr = getFormattedValue(xDataField, xFormatter, aNullDate, nFormatKey, nKeyType);
3075 aStringList.push_back(aStr);
3076 (void)xListCursor->next();
3079 // filling the entries for the combobox
3080 for (const auto& rString : aStringList)
3081 static_cast<ComboBox*>(m_pWindow.get())->InsertEntry(rString);
3085 OUString DbFilterField::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
3087 return OUString();
3091 void DbFilterField::UpdateFromField(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/)
3093 OSL_FAIL( "DbFilterField::UpdateFromField: cannot update a filter control from a field!" );
3097 IMPL_LINK_NOARG(DbFilterField, OnClick, VclPtr<CheckBox>, void)
3099 TriState eState = static_cast<CheckBoxControl*>(m_pWindow.get())->GetBox().GetState();
3100 OUStringBuffer aTextBuf;
3102 Reference< XRowSet > xDataSourceRowSet(
3103 Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY);
3104 Reference< XConnection > xConnection(getConnection(xDataSourceRowSet));
3105 const sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( xConnection ).getBooleanComparisonMode();
3107 switch (eState)
3109 case TRISTATE_TRUE:
3110 ::dbtools::getBooleanComparisonPredicate("", true, nBooleanComparisonMode, aTextBuf);
3111 break;
3112 case TRISTATE_FALSE:
3113 ::dbtools::getBooleanComparisonPredicate("", false, nBooleanComparisonMode, aTextBuf);
3114 break;
3115 case TRISTATE_INDET:
3116 break;
3119 const OUString aText(aTextBuf.makeStringAndClear());
3121 if (m_aText != aText)
3123 m_aText = aText;
3124 m_aCommitLink.Call(*this);
3129 FmXGridCell::FmXGridCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> _pControl )
3130 :OComponentHelper(m_aMutex)
3131 ,m_pColumn(pColumn)
3132 ,m_pCellControl( std::move(_pControl) )
3133 ,m_aWindowListeners( m_aMutex )
3134 ,m_aFocusListeners( m_aMutex )
3135 ,m_aKeyListeners( m_aMutex )
3136 ,m_aMouseListeners( m_aMutex )
3137 ,m_aMouseMotionListeners( m_aMutex )
3142 void FmXGridCell::init()
3144 vcl::Window* pEventWindow( getEventWindow() );
3145 if ( pEventWindow )
3146 pEventWindow->AddEventListener( LINK( this, FmXGridCell, OnWindowEvent ) );
3150 vcl::Window* FmXGridCell::getEventWindow() const
3152 if ( m_pCellControl )
3153 return &m_pCellControl->GetWindow();
3154 return nullptr;
3158 FmXGridCell::~FmXGridCell()
3160 if (!OComponentHelper::rBHelper.bDisposed)
3162 acquire();
3163 dispose();
3169 void FmXGridCell::SetTextLineColor()
3171 if (m_pCellControl)
3172 m_pCellControl->SetTextLineColor();
3176 void FmXGridCell::SetTextLineColor(const Color& _rColor)
3178 if (m_pCellControl)
3179 m_pCellControl->SetTextLineColor(_rColor);
3182 // XTypeProvider
3184 Sequence< Type > SAL_CALL FmXGridCell::getTypes( )
3186 Sequence< uno::Type > aTypes = ::comphelper::concatSequences(
3187 ::cppu::OComponentHelper::getTypes(),
3188 FmXGridCell_Base::getTypes()
3190 if ( m_pCellControl )
3191 aTypes = ::comphelper::concatSequences(
3192 aTypes,
3193 FmXGridCell_WindowBase::getTypes()
3195 return aTypes;
3199 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXGridCell )
3201 // OComponentHelper
3203 void FmXGridCell::disposing()
3205 lang::EventObject aEvent( *this );
3206 m_aWindowListeners.disposeAndClear( aEvent );
3207 m_aFocusListeners.disposeAndClear( aEvent );
3208 m_aKeyListeners.disposeAndClear( aEvent );
3209 m_aMouseListeners.disposeAndClear( aEvent );
3210 m_aMouseMotionListeners.disposeAndClear( aEvent );
3212 OComponentHelper::disposing();
3213 m_pColumn = nullptr;
3214 m_pCellControl.reset();
3218 Any SAL_CALL FmXGridCell::queryAggregation( const css::uno::Type& _rType )
3220 Any aReturn = OComponentHelper::queryAggregation( _rType );
3222 if ( !aReturn.hasValue() )
3223 aReturn = FmXGridCell_Base::queryInterface( _rType );
3225 if ( !aReturn.hasValue() && ( m_pCellControl != nullptr ) )
3226 aReturn = FmXGridCell_WindowBase::queryInterface( _rType );
3228 return aReturn;
3231 // css::awt::XControl
3233 Reference< XInterface > FmXGridCell::getContext()
3235 return Reference< XInterface > ();
3239 Reference< css::awt::XControlModel > FmXGridCell::getModel()
3241 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3242 return Reference< css::awt::XControlModel > (m_pColumn->getModel(), UNO_QUERY);
3245 // css::form::XBoundControl
3247 sal_Bool FmXGridCell::getLock()
3249 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3250 return m_pColumn->isLocked();
3254 void FmXGridCell::setLock(sal_Bool _bLock)
3256 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3257 if (getLock() == _bLock)
3258 return;
3259 else
3261 ::osl::MutexGuard aGuard(m_aMutex);
3262 m_pColumn->setLock(_bLock);
3267 void SAL_CALL FmXGridCell::setPosSize( ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int16 )
3269 OSL_FAIL( "FmXGridCell::setPosSize: not implemented" );
3270 // not allowed to tamper with this for a grid cell
3274 awt::Rectangle SAL_CALL FmXGridCell::getPosSize( )
3276 OSL_FAIL( "FmXGridCell::getPosSize: not implemented" );
3277 return awt::Rectangle();
3281 void SAL_CALL FmXGridCell::setVisible( sal_Bool )
3283 OSL_FAIL( "FmXGridCell::setVisible: not implemented" );
3284 // not allowed to tamper with this for a grid cell
3288 void SAL_CALL FmXGridCell::setEnable( sal_Bool )
3290 OSL_FAIL( "FmXGridCell::setEnable: not implemented" );
3291 // not allowed to tamper with this for a grid cell
3295 void SAL_CALL FmXGridCell::setFocus( )
3297 OSL_FAIL( "FmXGridCell::setFocus: not implemented" );
3298 // not allowed to tamper with this for a grid cell
3302 void SAL_CALL FmXGridCell::addWindowListener( const Reference< awt::XWindowListener >& _rxListener )
3304 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3305 m_aWindowListeners.addInterface( _rxListener );
3309 void SAL_CALL FmXGridCell::removeWindowListener( const Reference< awt::XWindowListener >& _rxListener )
3311 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3312 m_aWindowListeners.removeInterface( _rxListener );
3316 void SAL_CALL FmXGridCell::addFocusListener( const Reference< awt::XFocusListener >& _rxListener )
3318 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3319 m_aFocusListeners.addInterface( _rxListener );
3323 void SAL_CALL FmXGridCell::removeFocusListener( const Reference< awt::XFocusListener >& _rxListener )
3325 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3326 m_aFocusListeners.removeInterface( _rxListener );
3330 void SAL_CALL FmXGridCell::addKeyListener( const Reference< awt::XKeyListener >& _rxListener )
3332 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3333 m_aKeyListeners.addInterface( _rxListener );
3337 void SAL_CALL FmXGridCell::removeKeyListener( const Reference< awt::XKeyListener >& _rxListener )
3339 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3340 m_aKeyListeners.removeInterface( _rxListener );
3344 void SAL_CALL FmXGridCell::addMouseListener( const Reference< awt::XMouseListener >& _rxListener )
3346 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3347 m_aMouseListeners.addInterface( _rxListener );
3351 void SAL_CALL FmXGridCell::removeMouseListener( const Reference< awt::XMouseListener >& _rxListener )
3353 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3354 m_aMouseListeners.removeInterface( _rxListener );
3358 void SAL_CALL FmXGridCell::addMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener )
3360 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3361 m_aMouseMotionListeners.addInterface( _rxListener );
3365 void SAL_CALL FmXGridCell::removeMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener )
3367 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3368 m_aMouseMotionListeners.removeInterface( _rxListener );
3372 void SAL_CALL FmXGridCell::addPaintListener( const Reference< awt::XPaintListener >& )
3374 OSL_FAIL( "FmXGridCell::addPaintListener: not implemented" );
3378 void SAL_CALL FmXGridCell::removePaintListener( const Reference< awt::XPaintListener >& )
3380 OSL_FAIL( "FmXGridCell::removePaintListener: not implemented" );
3384 IMPL_LINK( FmXGridCell, OnWindowEvent, VclWindowEvent&, _rEvent, void )
3386 ENSURE_OR_THROW( _rEvent.GetWindow(), "illegal window" );
3387 onWindowEvent( _rEvent.GetId(), *_rEvent.GetWindow(), _rEvent.GetData() );
3391 void FmXGridCell::onFocusGained( const awt::FocusEvent& _rEvent )
3393 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3394 m_aFocusListeners.notifyEach( &awt::XFocusListener::focusGained, _rEvent );
3398 void FmXGridCell::onFocusLost( const awt::FocusEvent& _rEvent )
3400 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3401 m_aFocusListeners.notifyEach( &awt::XFocusListener::focusLost, _rEvent );
3405 void FmXGridCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
3407 switch ( _nEventId )
3409 case VclEventId::ControlGetFocus:
3410 case VclEventId::WindowGetFocus:
3411 case VclEventId::ControlLoseFocus:
3412 case VclEventId::WindowLoseFocus:
3414 if ( ( _rWindow.IsCompoundControl()
3415 && ( _nEventId == VclEventId::ControlGetFocus
3416 || _nEventId == VclEventId::ControlLoseFocus
3419 || ( !_rWindow.IsCompoundControl()
3420 && ( _nEventId == VclEventId::WindowGetFocus
3421 || _nEventId == VclEventId::WindowLoseFocus
3426 if ( !m_aFocusListeners.getLength() )
3427 break;
3429 bool bFocusGained = ( _nEventId == VclEventId::ControlGetFocus ) || ( _nEventId == VclEventId::WindowGetFocus );
3431 awt::FocusEvent aEvent;
3432 aEvent.Source = *this;
3433 aEvent.FocusFlags = static_cast<sal_Int16>(_rWindow.GetGetFocusFlags());
3434 aEvent.Temporary = false;
3436 if ( bFocusGained )
3437 onFocusGained( aEvent );
3438 else
3439 onFocusLost( aEvent );
3442 break;
3443 case VclEventId::WindowMouseButtonDown:
3444 case VclEventId::WindowMouseButtonUp:
3446 if ( !m_aMouseListeners.getLength() )
3447 break;
3449 const bool bButtonDown = ( _nEventId == VclEventId::WindowMouseButtonDown );
3451 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast< const ::MouseEvent* >( _pEventData ), *this ) );
3452 m_aMouseListeners.notifyEach( bButtonDown ? &awt::XMouseListener::mousePressed : &awt::XMouseListener::mouseReleased, aEvent );
3454 break;
3455 case VclEventId::WindowMouseMove:
3457 const MouseEvent& rMouseEvent = *static_cast< const ::MouseEvent* >( _pEventData );
3458 if ( rMouseEvent.IsEnterWindow() || rMouseEvent.IsLeaveWindow() )
3460 if ( m_aMouseListeners.getLength() != 0 )
3462 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) );
3463 m_aMouseListeners.notifyEach( rMouseEvent.IsEnterWindow() ? &awt::XMouseListener::mouseEntered: &awt::XMouseListener::mouseExited, aEvent );
3466 else if ( !rMouseEvent.IsEnterWindow() && !rMouseEvent.IsLeaveWindow() )
3468 if ( m_aMouseMotionListeners.getLength() != 0 )
3470 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) );
3471 aEvent.ClickCount = 0;
3472 const bool bSimpleMove = bool( rMouseEvent.GetMode() & MouseEventModifiers::SIMPLEMOVE );
3473 m_aMouseMotionListeners.notifyEach( bSimpleMove ? &awt::XMouseMotionListener::mouseMoved: &awt::XMouseMotionListener::mouseDragged, aEvent );
3477 break;
3478 case VclEventId::WindowKeyInput:
3479 case VclEventId::WindowKeyUp:
3481 if ( !m_aKeyListeners.getLength() )
3482 break;
3484 const bool bKeyPressed = ( _nEventId == VclEventId::WindowKeyInput );
3485 awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent( *static_cast< const ::KeyEvent* >( _pEventData ), *this ) );
3486 m_aKeyListeners.notifyEach( bKeyPressed ? &awt::XKeyListener::keyPressed: &awt::XKeyListener::keyReleased, aEvent );
3488 break;
3489 default: break;
3494 void FmXDataCell::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect,
3495 const Reference< css::sdb::XColumn >& _rxField,
3496 const Reference< XNumberFormatter >& xFormatter)
3498 m_pCellControl->PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
3502 void FmXDataCell::UpdateFromColumn()
3504 Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue());
3505 if (xField.is())
3506 m_pCellControl->UpdateFromField(xField, m_pColumn->GetParent().getNumberFormatter());
3510 FmXTextCell::FmXTextCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
3511 :FmXDataCell( pColumn, std::move(pControl) )
3512 ,m_bFastPaint( true )
3517 void FmXTextCell::PaintFieldToCell(OutputDevice& rDev,
3518 const tools::Rectangle& rRect,
3519 const Reference< css::sdb::XColumn >& _rxField,
3520 const Reference< XNumberFormatter >& xFormatter)
3522 if ( !m_bFastPaint )
3524 FmXDataCell::PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
3525 return;
3528 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter;
3529 if ( ( rDev.GetOutDevType() == OUTDEV_WINDOW ) && !static_cast< vcl::Window& >( rDev ).IsEnabled() )
3530 nStyle |= DrawTextFlags::Disable;
3532 switch (m_pColumn->GetAlignment())
3534 case css::awt::TextAlign::RIGHT:
3535 nStyle |= DrawTextFlags::Right;
3536 break;
3537 case css::awt::TextAlign::CENTER:
3538 nStyle |= DrawTextFlags::Center;
3539 break;
3540 default:
3541 nStyle |= DrawTextFlags::Left;
3546 Color* pColor = nullptr;
3547 OUString aText = GetText(_rxField, xFormatter, &pColor);
3548 if (pColor != nullptr)
3550 Color aOldTextColor( rDev.GetTextColor() );
3551 rDev.SetTextColor( *pColor );
3552 rDev.DrawText(rRect, aText, nStyle);
3553 rDev.SetTextColor( aOldTextColor );
3555 else
3556 rDev.DrawText(rRect, aText, nStyle);
3558 catch (const Exception&)
3560 TOOLS_WARN_EXCEPTION("svx.fmcomp", "PaintFieldToCell");
3564 FmXEditCell::FmXEditCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
3565 :FmXTextCell( pColumn, std::move(pControl) )
3566 ,m_aTextListeners(m_aMutex)
3567 ,m_aChangeListeners( m_aMutex )
3568 ,m_pEditImplementation( nullptr )
3569 ,m_bOwnEditImplementation( false )
3572 DbTextField* pTextField = dynamic_cast<DbTextField*>( m_pCellControl.get() );
3573 if ( pTextField )
3576 m_pEditImplementation = pTextField->GetEditImplementation();
3577 if ( !pTextField->IsSimpleEdit() )
3578 m_bFastPaint = false;
3580 else
3582 m_pEditImplementation = new EditImplementation( static_cast< Edit& >( m_pCellControl->GetWindow() ) );
3583 m_bOwnEditImplementation = true;
3588 FmXEditCell::~FmXEditCell()
3590 if (!OComponentHelper::rBHelper.bDisposed)
3592 acquire();
3593 dispose();
3599 // OComponentHelper
3601 void FmXEditCell::disposing()
3603 css::lang::EventObject aEvt(*this);
3604 m_aTextListeners.disposeAndClear(aEvt);
3605 m_aChangeListeners.disposeAndClear(aEvt);
3607 m_pEditImplementation->SetModifyHdl( Link<Edit&,void>() );
3608 if ( m_bOwnEditImplementation )
3609 delete m_pEditImplementation;
3610 m_pEditImplementation = nullptr;
3612 FmXDataCell::disposing();
3616 Any SAL_CALL FmXEditCell::queryAggregation( const css::uno::Type& _rType )
3618 Any aReturn = FmXTextCell::queryAggregation( _rType );
3620 if ( !aReturn.hasValue() )
3621 aReturn = FmXEditCell_Base::queryInterface( _rType );
3623 return aReturn;
3627 Sequence< css::uno::Type > SAL_CALL FmXEditCell::getTypes( )
3629 return ::comphelper::concatSequences(
3630 FmXTextCell::getTypes(),
3631 FmXEditCell_Base::getTypes()
3636 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXEditCell )
3638 // css::awt::XTextComponent
3640 void SAL_CALL FmXEditCell::addTextListener(const Reference< css::awt::XTextListener >& l)
3642 m_aTextListeners.addInterface( l );
3646 void SAL_CALL FmXEditCell::removeTextListener(const Reference< css::awt::XTextListener >& l)
3648 m_aTextListeners.removeInterface( l );
3652 void SAL_CALL FmXEditCell::setText( const OUString& aText )
3654 ::osl::MutexGuard aGuard( m_aMutex );
3656 if ( m_pEditImplementation )
3658 m_pEditImplementation->SetText( aText );
3660 // In Java, a textChanged is fired as well; not in VCL.
3661 // css::awt::Toolkit must be Java-compliant...
3662 onTextChanged();
3667 void SAL_CALL FmXEditCell::insertText(const css::awt::Selection& rSel, const OUString& aText)
3669 ::osl::MutexGuard aGuard( m_aMutex );
3671 if ( m_pEditImplementation )
3673 m_pEditImplementation->SetSelection( Selection( rSel.Min, rSel.Max ) );
3674 m_pEditImplementation->ReplaceSelected( aText );
3679 OUString SAL_CALL FmXEditCell::getText()
3681 ::osl::MutexGuard aGuard( m_aMutex );
3683 OUString aText;
3684 if ( m_pEditImplementation )
3686 if ( m_pEditImplementation->GetControl().IsVisible() && m_pColumn->GetParent().getDisplaySynchron())
3688 // if the display isn't sync with the cursor we can't ask the edit field
3689 LineEnd eLineEndFormat = getModelLineEndSetting( m_pColumn->getModel() );
3690 aText = m_pEditImplementation->GetText( eLineEndFormat );
3692 else
3694 Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue());
3695 if (xField.is())
3696 aText = GetText(xField, m_pColumn->GetParent().getNumberFormatter());
3699 return aText;
3703 OUString SAL_CALL FmXEditCell::getSelectedText()
3705 ::osl::MutexGuard aGuard( m_aMutex );
3707 OUString aText;
3708 if ( m_pEditImplementation )
3710 LineEnd eLineEndFormat = m_pColumn ? getModelLineEndSetting( m_pColumn->getModel() ) : LINEEND_LF;
3711 aText = m_pEditImplementation->GetSelected( eLineEndFormat );
3713 return aText;
3717 void SAL_CALL FmXEditCell::setSelection( const css::awt::Selection& aSelection )
3719 ::osl::MutexGuard aGuard( m_aMutex );
3721 if ( m_pEditImplementation )
3722 m_pEditImplementation->SetSelection( Selection( aSelection.Min, aSelection.Max ) );
3726 css::awt::Selection SAL_CALL FmXEditCell::getSelection()
3728 ::osl::MutexGuard aGuard( m_aMutex );
3730 Selection aSel;
3731 if ( m_pEditImplementation )
3732 aSel = m_pEditImplementation->GetSelection();
3734 return css::awt::Selection(aSel.Min(), aSel.Max());
3738 sal_Bool SAL_CALL FmXEditCell::isEditable()
3740 ::osl::MutexGuard aGuard( m_aMutex );
3742 return m_pEditImplementation && !m_pEditImplementation->IsReadOnly() && m_pEditImplementation->GetControl().IsEnabled();
3746 void SAL_CALL FmXEditCell::setEditable( sal_Bool bEditable )
3748 ::osl::MutexGuard aGuard( m_aMutex );
3750 if ( m_pEditImplementation )
3751 m_pEditImplementation->SetReadOnly( !bEditable );
3755 sal_Int16 SAL_CALL FmXEditCell::getMaxTextLen()
3757 ::osl::MutexGuard aGuard( m_aMutex );
3759 return m_pEditImplementation ? m_pEditImplementation->GetMaxTextLen() : 0;
3763 void SAL_CALL FmXEditCell::setMaxTextLen( sal_Int16 nLen )
3765 ::osl::MutexGuard aGuard( m_aMutex );
3767 if ( m_pEditImplementation )
3768 m_pEditImplementation->SetMaxTextLen( nLen );
3772 void SAL_CALL FmXEditCell::addChangeListener( const Reference< form::XChangeListener >& Listener )
3774 m_aChangeListeners.addInterface( Listener );
3778 void SAL_CALL FmXEditCell::removeChangeListener( const Reference< form::XChangeListener >& Listener )
3780 m_aChangeListeners.removeInterface( Listener );
3784 void FmXEditCell::onTextChanged()
3786 css::awt::TextEvent aEvent;
3787 aEvent.Source = *this;
3788 m_aTextListeners.notifyEach( &awt::XTextListener::textChanged, aEvent );
3792 void FmXEditCell::onFocusGained( const awt::FocusEvent& _rEvent )
3794 FmXTextCell::onFocusGained( _rEvent );
3795 m_sValueOnEnter = getText();
3799 void FmXEditCell::onFocusLost( const awt::FocusEvent& _rEvent )
3801 FmXTextCell::onFocusLost( _rEvent );
3803 if ( getText() != m_sValueOnEnter )
3805 lang::EventObject aEvent( *this );
3806 m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvent );
3811 void FmXEditCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
3813 switch ( _nEventId )
3815 case VclEventId::EditModify:
3817 if ( m_pEditImplementation && m_aTextListeners.getLength() )
3818 onTextChanged();
3819 return;
3821 default: break;
3824 FmXTextCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
3827 FmXCheckBoxCell::FmXCheckBoxCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
3828 :FmXDataCell( pColumn, std::move(pControl) )
3829 ,m_aItemListeners(m_aMutex)
3830 ,m_aActionListeners( m_aMutex )
3831 ,m_pBox( & static_cast< CheckBoxControl& >( m_pCellControl->GetWindow() ).GetBox() )
3836 FmXCheckBoxCell::~FmXCheckBoxCell()
3838 if (!OComponentHelper::rBHelper.bDisposed)
3840 acquire();
3841 dispose();
3846 // OComponentHelper
3848 void FmXCheckBoxCell::disposing()
3850 css::lang::EventObject aEvt(*this);
3851 m_aItemListeners.disposeAndClear(aEvt);
3852 m_aActionListeners.disposeAndClear(aEvt);
3854 static_cast< CheckBoxControl& >( m_pCellControl->GetWindow() ).SetClickHdl(Link<VclPtr<CheckBox>,void>());
3855 m_pBox = nullptr;
3857 FmXDataCell::disposing();
3861 Any SAL_CALL FmXCheckBoxCell::queryAggregation( const css::uno::Type& _rType )
3863 Any aReturn = FmXDataCell::queryAggregation( _rType );
3865 if ( !aReturn.hasValue() )
3866 aReturn = FmXCheckBoxCell_Base::queryInterface( _rType );
3868 return aReturn;
3872 Sequence< css::uno::Type > SAL_CALL FmXCheckBoxCell::getTypes( )
3874 return ::comphelper::concatSequences(
3875 FmXDataCell::getTypes(),
3876 FmXCheckBoxCell_Base::getTypes()
3881 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXCheckBoxCell )
3884 void SAL_CALL FmXCheckBoxCell::addItemListener( const Reference< css::awt::XItemListener >& l )
3886 m_aItemListeners.addInterface( l );
3890 void SAL_CALL FmXCheckBoxCell::removeItemListener( const Reference< css::awt::XItemListener >& l )
3892 m_aItemListeners.removeInterface( l );
3896 void SAL_CALL FmXCheckBoxCell::setState( sal_Int16 n )
3898 ::osl::MutexGuard aGuard( m_aMutex );
3900 if (m_pBox)
3902 UpdateFromColumn();
3903 m_pBox->SetState( static_cast<TriState>(n) );
3908 sal_Int16 SAL_CALL FmXCheckBoxCell::getState()
3910 ::osl::MutexGuard aGuard( m_aMutex );
3912 if (m_pBox)
3914 UpdateFromColumn();
3915 return static_cast<sal_Int16>(m_pBox->GetState());
3917 return TRISTATE_INDET;
3921 void SAL_CALL FmXCheckBoxCell::enableTriState( sal_Bool b )
3923 ::osl::MutexGuard aGuard( m_aMutex );
3925 if (m_pBox)
3926 m_pBox->EnableTriState( b );
3930 void SAL_CALL FmXCheckBoxCell::addActionListener( const Reference< awt::XActionListener >& Listener )
3932 m_aActionListeners.addInterface( Listener );
3936 void SAL_CALL FmXCheckBoxCell::removeActionListener( const Reference< awt::XActionListener >& Listener )
3938 m_aActionListeners.removeInterface( Listener );
3942 void SAL_CALL FmXCheckBoxCell::setLabel( const OUString& Label )
3944 SolarMutexGuard aGuard;
3945 if ( m_pColumn )
3947 DbGridControl& rGrid( m_pColumn->GetParent() );
3948 rGrid.SetColumnTitle( rGrid.GetColumnId( m_pColumn->GetFieldPos() ), Label );
3953 void SAL_CALL FmXCheckBoxCell::setActionCommand( const OUString& Command )
3955 m_aActionCommand = Command;
3959 vcl::Window* FmXCheckBoxCell::getEventWindow() const
3961 return m_pBox;
3965 void FmXCheckBoxCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
3967 switch ( _nEventId )
3969 case VclEventId::CheckboxToggle:
3971 // check boxes are to be committed immediately (this holds for ordinary check box controls in
3972 // documents, and this must hold for check boxes in grid columns, too
3973 // 91210 - 22.08.2001 - frank.schoenheit@sun.com
3974 m_pCellControl->Commit();
3976 Reference< XWindow > xKeepAlive( this );
3977 if ( m_aItemListeners.getLength() && m_pBox )
3979 awt::ItemEvent aEvent;
3980 aEvent.Source = *this;
3981 aEvent.Highlighted = 0;
3982 aEvent.Selected = m_pBox->GetState();
3983 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
3985 if ( m_aActionListeners.getLength() )
3987 awt::ActionEvent aEvent;
3988 aEvent.Source = *this;
3989 aEvent.ActionCommand = m_aActionCommand;
3990 m_aActionListeners.notifyEach( &awt::XActionListener::actionPerformed, aEvent );
3993 break;
3995 default:
3996 FmXDataCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
3997 break;
4001 FmXListBoxCell::FmXListBoxCell(DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl)
4002 :FmXTextCell( pColumn, std::move(pControl) )
4003 ,m_aItemListeners(m_aMutex)
4004 ,m_aActionListeners(m_aMutex)
4005 ,m_pBox( &static_cast< ListBox& >( m_pCellControl->GetWindow() ) )
4008 m_pBox->SetDoubleClickHdl( LINK( this, FmXListBoxCell, OnDoubleClick ) );
4012 FmXListBoxCell::~FmXListBoxCell()
4014 if (!OComponentHelper::rBHelper.bDisposed)
4016 acquire();
4017 dispose();
4022 // OComponentHelper
4024 void FmXListBoxCell::disposing()
4026 css::lang::EventObject aEvt(*this);
4027 m_aItemListeners.disposeAndClear(aEvt);
4028 m_aActionListeners.disposeAndClear(aEvt);
4030 m_pBox->SetSelectHdl( Link<ListBox&,void>() );
4031 m_pBox->SetDoubleClickHdl( Link<ListBox&,void>() );
4032 m_pBox = nullptr;
4034 FmXTextCell::disposing();
4038 Any SAL_CALL FmXListBoxCell::queryAggregation( const css::uno::Type& _rType )
4040 Any aReturn = FmXTextCell::queryAggregation(_rType);
4042 if ( !aReturn.hasValue() )
4043 aReturn = FmXListBoxCell_Base::queryInterface( _rType );
4045 return aReturn;
4049 Sequence< css::uno::Type > SAL_CALL FmXListBoxCell::getTypes( )
4051 return ::comphelper::concatSequences(
4052 FmXTextCell::getTypes(),
4053 FmXListBoxCell_Base::getTypes()
4058 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXListBoxCell )
4061 void SAL_CALL FmXListBoxCell::addItemListener(const Reference< css::awt::XItemListener >& l)
4063 m_aItemListeners.addInterface( l );
4067 void SAL_CALL FmXListBoxCell::removeItemListener(const Reference< css::awt::XItemListener >& l)
4069 m_aItemListeners.removeInterface( l );
4073 void SAL_CALL FmXListBoxCell::addActionListener(const Reference< css::awt::XActionListener >& l)
4075 m_aActionListeners.addInterface( l );
4079 void SAL_CALL FmXListBoxCell::removeActionListener(const Reference< css::awt::XActionListener >& l)
4081 m_aActionListeners.removeInterface( l );
4085 void SAL_CALL FmXListBoxCell::addItem(const OUString& aItem, sal_Int16 nPos)
4087 ::osl::MutexGuard aGuard( m_aMutex );
4088 if (m_pBox)
4089 m_pBox->InsertEntry( aItem, nPos );
4093 void SAL_CALL FmXListBoxCell::addItems(const css::uno::Sequence<OUString>& aItems, sal_Int16 nPos)
4095 ::osl::MutexGuard aGuard( m_aMutex );
4096 if (m_pBox)
4098 sal_uInt16 nP = nPos;
4099 for ( const auto& rItem : aItems )
4101 m_pBox->InsertEntry( rItem, nP );
4102 if ( nPos != -1 ) // Not if 0xFFFF, because LIST_APPEND
4103 nP++;
4109 void SAL_CALL FmXListBoxCell::removeItems(sal_Int16 nPos, sal_Int16 nCount)
4111 ::osl::MutexGuard aGuard( m_aMutex );
4112 if ( m_pBox )
4114 for ( sal_uInt16 n = nCount; n; )
4115 m_pBox->RemoveEntry( nPos + (--n) );
4120 sal_Int16 SAL_CALL FmXListBoxCell::getItemCount()
4122 ::osl::MutexGuard aGuard( m_aMutex );
4123 return m_pBox ? m_pBox->GetEntryCount() : 0;
4127 OUString SAL_CALL FmXListBoxCell::getItem(sal_Int16 nPos)
4129 ::osl::MutexGuard aGuard( m_aMutex );
4130 return m_pBox ? m_pBox->GetEntry(nPos) : OUString();
4133 css::uno::Sequence<OUString> SAL_CALL FmXListBoxCell::getItems()
4135 ::osl::MutexGuard aGuard( m_aMutex );
4137 css::uno::Sequence<OUString> aSeq;
4138 if (m_pBox)
4140 const sal_Int32 nEntries = m_pBox ->GetEntryCount();
4141 aSeq = css::uno::Sequence<OUString>( nEntries );
4142 for ( sal_Int32 n = nEntries; n; )
4144 --n;
4145 aSeq.getArray()[n] = m_pBox ->GetEntry( n );
4148 return aSeq;
4152 sal_Int16 SAL_CALL FmXListBoxCell::getSelectedItemPos()
4154 ::osl::MutexGuard aGuard( m_aMutex );
4155 if (m_pBox)
4157 UpdateFromColumn();
4158 sal_Int32 nPos = m_pBox->GetSelectedEntryPos();
4159 if (nPos > SHRT_MAX || nPos < SHRT_MIN)
4160 throw std::out_of_range("awt::XListBox::getSelectedItemPos can only return a short");
4161 return nPos;
4163 return 0;
4167 Sequence< sal_Int16 > SAL_CALL FmXListBoxCell::getSelectedItemsPos()
4169 ::osl::MutexGuard aGuard( m_aMutex );
4170 Sequence<sal_Int16> aSeq;
4172 if (m_pBox)
4174 UpdateFromColumn();
4175 const sal_Int32 nSelEntries = m_pBox->GetSelectedEntryCount();
4176 aSeq = Sequence<sal_Int16>( nSelEntries );
4177 for ( sal_Int32 n = 0; n < nSelEntries; ++n )
4178 aSeq.getArray()[n] = m_pBox->GetSelectedEntryPos( n );
4180 return aSeq;
4183 OUString SAL_CALL FmXListBoxCell::getSelectedItem()
4185 ::osl::MutexGuard aGuard( m_aMutex );
4187 OUString aItem;
4189 if (m_pBox)
4191 UpdateFromColumn();
4192 aItem = m_pBox->GetSelectedEntry();
4195 return aItem;
4199 css::uno::Sequence<OUString> SAL_CALL FmXListBoxCell::getSelectedItems()
4201 ::osl::MutexGuard aGuard( m_aMutex );
4203 css::uno::Sequence<OUString> aSeq;
4205 if (m_pBox)
4207 UpdateFromColumn();
4208 const sal_Int32 nSelEntries = m_pBox->GetSelectedEntryCount();
4209 aSeq = css::uno::Sequence<OUString>( nSelEntries );
4210 for ( sal_Int32 n = 0; n < nSelEntries; ++n )
4211 aSeq.getArray()[n] = m_pBox->GetSelectedEntry( n );
4213 return aSeq;
4217 void SAL_CALL FmXListBoxCell::selectItemPos(sal_Int16 nPos, sal_Bool bSelect)
4219 ::osl::MutexGuard aGuard( m_aMutex );
4221 if (m_pBox)
4222 m_pBox->SelectEntryPos( nPos, bSelect );
4226 void SAL_CALL FmXListBoxCell::selectItemsPos(const Sequence< sal_Int16 >& aPositions, sal_Bool bSelect)
4228 ::osl::MutexGuard aGuard( m_aMutex );
4230 if (m_pBox)
4232 for ( sal_uInt16 n = static_cast<sal_uInt16>(aPositions.getLength()); n; )
4233 m_pBox->SelectEntryPos( static_cast<sal_uInt16>(aPositions.getConstArray()[--n]), bSelect );
4238 void SAL_CALL FmXListBoxCell::selectItem(const OUString& aItem, sal_Bool bSelect)
4240 ::osl::MutexGuard aGuard( m_aMutex );
4242 if (m_pBox)
4243 m_pBox->SelectEntry( aItem, bSelect );
4247 sal_Bool SAL_CALL FmXListBoxCell::isMutipleMode()
4249 ::osl::MutexGuard aGuard( m_aMutex );
4251 bool bMulti = false;
4252 if (m_pBox)
4253 bMulti = m_pBox->IsMultiSelectionEnabled();
4254 return bMulti;
4258 void SAL_CALL FmXListBoxCell::setMultipleMode(sal_Bool bMulti)
4260 ::osl::MutexGuard aGuard( m_aMutex );
4262 if (m_pBox)
4263 m_pBox->EnableMultiSelection( bMulti );
4267 sal_Int16 SAL_CALL FmXListBoxCell::getDropDownLineCount()
4269 ::osl::MutexGuard aGuard( m_aMutex );
4271 sal_Int16 nLines = 0;
4272 if (m_pBox)
4273 nLines = m_pBox->GetDropDownLineCount();
4275 return nLines;
4279 void SAL_CALL FmXListBoxCell::setDropDownLineCount(sal_Int16 nLines)
4281 ::osl::MutexGuard aGuard( m_aMutex );
4283 if (m_pBox)
4284 m_pBox->SetDropDownLineCount( nLines );
4288 void SAL_CALL FmXListBoxCell::makeVisible(sal_Int16 nEntry)
4290 ::osl::MutexGuard aGuard( m_aMutex );
4292 if (m_pBox)
4293 m_pBox->SetTopEntry( nEntry );
4297 void FmXListBoxCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
4299 if ( ( &_rWindow == m_pBox )
4300 && ( _nEventId == VclEventId::ListboxSelect )
4303 OnDoubleClick( *m_pBox );
4305 css::awt::ItemEvent aEvent;
4306 aEvent.Source = *this;
4307 aEvent.Highlighted = 0;
4309 // with multiple selection 0xFFFF, otherwise the ID
4310 aEvent.Selected = (m_pBox->GetSelectedEntryCount() == 1 )
4311 ? m_pBox->GetSelectedEntryPos() : 0xFFFF;
4313 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
4314 return;
4317 FmXTextCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
4321 IMPL_LINK_NOARG(FmXListBoxCell, OnDoubleClick, ListBox&, void)
4323 if (m_pBox)
4325 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aActionListeners );
4327 css::awt::ActionEvent aEvent;
4328 aEvent.Source = *this;
4329 aEvent.ActionCommand = m_pBox->GetSelectedEntry();
4331 while( aIt.hasMoreElements() )
4332 static_cast< css::awt::XActionListener *>(aIt.next())->actionPerformed( aEvent );
4336 FmXComboBoxCell::FmXComboBoxCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
4337 :FmXTextCell( pColumn, std::move(pControl) )
4338 ,m_aItemListeners( m_aMutex )
4339 ,m_aActionListeners( m_aMutex )
4340 ,m_pComboBox( &static_cast< ComboBox& >( m_pCellControl->GetWindow() ) )
4345 FmXComboBoxCell::~FmXComboBoxCell()
4347 if ( !OComponentHelper::rBHelper.bDisposed )
4349 acquire();
4350 dispose();
4356 void FmXComboBoxCell::disposing()
4358 css::lang::EventObject aEvt(*this);
4359 m_aItemListeners.disposeAndClear(aEvt);
4360 m_aActionListeners.disposeAndClear(aEvt);
4362 FmXTextCell::disposing();
4366 Any SAL_CALL FmXComboBoxCell::queryAggregation( const css::uno::Type& _rType )
4368 Any aReturn = FmXTextCell::queryAggregation(_rType);
4370 if ( !aReturn.hasValue() )
4371 aReturn = FmXComboBoxCell_Base::queryInterface( _rType );
4373 return aReturn;
4377 Sequence< Type > SAL_CALL FmXComboBoxCell::getTypes( )
4379 return ::comphelper::concatSequences(
4380 FmXTextCell::getTypes(),
4381 FmXComboBoxCell_Base::getTypes()
4386 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXComboBoxCell )
4389 void SAL_CALL FmXComboBoxCell::addItemListener(const Reference< awt::XItemListener >& l)
4391 m_aItemListeners.addInterface( l );
4395 void SAL_CALL FmXComboBoxCell::removeItemListener(const Reference< awt::XItemListener >& l)
4397 m_aItemListeners.removeInterface( l );
4401 void SAL_CALL FmXComboBoxCell::addActionListener(const Reference< awt::XActionListener >& l)
4403 m_aActionListeners.addInterface( l );
4407 void SAL_CALL FmXComboBoxCell::removeActionListener(const Reference< awt::XActionListener >& l)
4409 m_aActionListeners.removeInterface( l );
4413 void SAL_CALL FmXComboBoxCell::addItem( const OUString& Item, sal_Int16 Pos )
4415 ::osl::MutexGuard aGuard( m_aMutex );
4416 if ( m_pComboBox )
4417 m_pComboBox->InsertEntry( Item, Pos );
4421 void SAL_CALL FmXComboBoxCell::addItems( const Sequence< OUString >& Items, sal_Int16 Pos )
4423 ::osl::MutexGuard aGuard( m_aMutex );
4424 if ( m_pComboBox )
4426 sal_uInt16 nP = Pos;
4427 for ( const auto& rItem : Items )
4429 m_pComboBox->InsertEntry( rItem, nP );
4430 if ( Pos != -1 )
4431 nP++;
4437 void SAL_CALL FmXComboBoxCell::removeItems( sal_Int16 Pos, sal_Int16 Count )
4439 ::osl::MutexGuard aGuard( m_aMutex );
4440 if ( m_pComboBox )
4442 for ( sal_uInt16 n = Count; n; )
4443 m_pComboBox->RemoveEntryAt( Pos + (--n) );
4448 sal_Int16 SAL_CALL FmXComboBoxCell::getItemCount()
4450 ::osl::MutexGuard aGuard( m_aMutex );
4451 return m_pComboBox ? m_pComboBox->GetEntryCount() : 0;
4455 OUString SAL_CALL FmXComboBoxCell::getItem( sal_Int16 Pos )
4457 ::osl::MutexGuard aGuard( m_aMutex );
4458 return m_pComboBox ? m_pComboBox->GetEntry(Pos) : OUString();
4461 Sequence< OUString > SAL_CALL FmXComboBoxCell::getItems()
4463 ::osl::MutexGuard aGuard( m_aMutex );
4465 Sequence< OUString > aItems;
4466 if ( m_pComboBox )
4468 const sal_Int32 nEntries = m_pComboBox->GetEntryCount();
4469 aItems.realloc( nEntries );
4470 OUString* pItem = aItems.getArray();
4471 for ( sal_Int32 n=0; n<nEntries; ++n, ++pItem )
4472 *pItem = m_pComboBox->GetEntry( n );
4474 return aItems;
4478 sal_Int16 SAL_CALL FmXComboBoxCell::getDropDownLineCount()
4480 ::osl::MutexGuard aGuard( m_aMutex );
4482 sal_Int16 nLines = 0;
4483 if ( m_pComboBox )
4484 nLines = m_pComboBox->GetDropDownLineCount();
4486 return nLines;
4490 void SAL_CALL FmXComboBoxCell::setDropDownLineCount(sal_Int16 nLines)
4492 ::osl::MutexGuard aGuard( m_aMutex );
4493 if ( m_pComboBox )
4494 m_pComboBox->SetDropDownLineCount( nLines );
4498 void FmXComboBoxCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
4501 switch ( _nEventId )
4503 case VclEventId::ComboboxSelect:
4505 awt::ItemEvent aEvent;
4506 aEvent.Source = *this;
4507 aEvent.Highlighted = 0;
4509 // with multiple selection 0xFFFF, otherwise the ID
4510 aEvent.Selected = ( m_pComboBox->GetSelectedEntryCount() == 1 )
4511 ? m_pComboBox->GetSelectedEntryPos()
4512 : 0xFFFF;
4513 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
4515 break;
4517 default:
4518 FmXTextCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
4519 break;
4524 FmXFilterCell::FmXFilterCell(DbGridColumn* pColumn, std::unique_ptr<DbFilterField> pControl )
4525 :FmXGridCell( pColumn, std::move(pControl) )
4526 ,m_aTextListeners(m_aMutex)
4528 static_cast<DbFilterField*>(m_pCellControl.get())->SetCommitHdl( LINK( this, FmXFilterCell, OnCommit ) );
4532 FmXFilterCell::~FmXFilterCell()
4534 if (!OComponentHelper::rBHelper.bDisposed)
4536 acquire();
4537 dispose();
4542 // XUnoTunnel
4544 sal_Int64 SAL_CALL FmXFilterCell::getSomething( const Sequence< sal_Int8 >& _rIdentifier )
4546 sal_Int64 nReturn(0);
4548 if ( isUnoTunnelId<FmXFilterCell>(_rIdentifier) )
4550 nReturn = reinterpret_cast<sal_Int64>(this);
4553 return nReturn;
4556 namespace
4558 class theFmXFilterCellUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theFmXFilterCellUnoTunnelId > {};
4561 const Sequence<sal_Int8>& FmXFilterCell::getUnoTunnelId()
4563 return theFmXFilterCellUnoTunnelId::get().getSeq();
4567 void FmXFilterCell::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect )
4569 static_cast< DbFilterField* >( m_pCellControl.get() )->PaintCell( rDev, rRect );
4572 // OComponentHelper
4574 void FmXFilterCell::disposing()
4576 css::lang::EventObject aEvt(*this);
4577 m_aTextListeners.disposeAndClear(aEvt);
4579 static_cast<DbFilterField*>(m_pCellControl.get())->SetCommitHdl(Link<DbFilterField&,void>());
4581 FmXGridCell::disposing();
4585 Any SAL_CALL FmXFilterCell::queryAggregation( const css::uno::Type& _rType )
4587 Any aReturn = FmXGridCell::queryAggregation(_rType);
4589 if ( !aReturn.hasValue() )
4590 aReturn = FmXFilterCell_Base::queryInterface( _rType );
4592 return aReturn;
4596 Sequence< css::uno::Type > SAL_CALL FmXFilterCell::getTypes( )
4598 return ::comphelper::concatSequences(
4599 FmXGridCell::getTypes(),
4600 FmXFilterCell_Base::getTypes()
4605 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXFilterCell )
4607 // css::awt::XTextComponent
4609 void SAL_CALL FmXFilterCell::addTextListener(const Reference< css::awt::XTextListener >& l)
4611 m_aTextListeners.addInterface( l );
4615 void SAL_CALL FmXFilterCell::removeTextListener(const Reference< css::awt::XTextListener >& l)
4617 m_aTextListeners.removeInterface( l );
4621 void SAL_CALL FmXFilterCell::setText( const OUString& aText )
4623 ::osl::MutexGuard aGuard( m_aMutex );
4624 static_cast<DbFilterField*>(m_pCellControl.get())->SetText(aText);
4628 void SAL_CALL FmXFilterCell::insertText( const css::awt::Selection& /*rSel*/, const OUString& /*aText*/ )
4633 OUString SAL_CALL FmXFilterCell::getText()
4635 ::osl::MutexGuard aGuard( m_aMutex );
4636 return static_cast<DbFilterField*>(m_pCellControl.get())->GetText();
4640 OUString SAL_CALL FmXFilterCell::getSelectedText()
4642 return getText();
4646 void SAL_CALL FmXFilterCell::setSelection( const css::awt::Selection& /*aSelection*/ )
4651 css::awt::Selection SAL_CALL FmXFilterCell::getSelection()
4653 return css::awt::Selection();
4657 sal_Bool SAL_CALL FmXFilterCell::isEditable()
4659 return true;
4663 void SAL_CALL FmXFilterCell::setEditable( sal_Bool /*bEditable*/ )
4668 sal_Int16 SAL_CALL FmXFilterCell::getMaxTextLen()
4670 return 0;
4674 void SAL_CALL FmXFilterCell::setMaxTextLen( sal_Int16 /*nLen*/ )
4679 IMPL_LINK_NOARG(FmXFilterCell, OnCommit, DbFilterField&, void)
4681 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aTextListeners );
4682 css::awt::TextEvent aEvt;
4683 aEvt.Source = *this;
4684 while( aIt.hasMoreElements() )
4685 static_cast< css::awt::XTextListener *>(aIt.next())->textChanged( aEvt );
4688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */