Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / svx / source / fmcomp / gridcell.cxx
blobfd2b83fe90403591f62460219354f3f46479c26f
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/log.hxx>
23 #include <fmprop.hxx>
24 #include <svx/strings.hrc>
25 #include <svx/fmtools.hxx>
26 #include <gridcell.hxx>
27 #include <gridcols.hxx>
28 #include <sdbdatacolumn.hxx>
30 #include <com/sun/star/awt/LineEndFormat.hpp>
31 #include <com/sun/star/awt/MouseWheelBehavior.hpp>
32 #include <com/sun/star/awt/VisualEffect.hpp>
33 #include <com/sun/star/container/XChild.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/form/FormComponentType.hpp>
36 #include <com/sun/star/form/XBoundComponent.hpp>
37 #include <com/sun/star/script/XEventAttacherManager.hpp>
38 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
39 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
40 #include <com/sun/star/sdbc/DataType.hpp>
41 #include <com/sun/star/sdbc/SQLException.hpp>
42 #include <com/sun/star/sdbc/XRowSet.hpp>
43 #include <com/sun/star/sdbc/XStatement.hpp>
44 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
45 #include <com/sun/star/util/XNumberFormatter.hpp>
46 #include <com/sun/star/util/Time.hpp>
47 #include <com/sun/star/util/Date.hpp>
49 #include <comphelper/numbers.hxx>
50 #include <comphelper/property.hxx>
51 #include <comphelper/servicehelper.hxx>
52 #include <comphelper/string.hxx>
53 #include <comphelper/types.hxx>
54 #include <connectivity/formattedcolumnvalue.hxx>
55 #include <i18nlangtag/lang.h>
57 #include <rtl/math.hxx>
58 #include <svl/numuno.hxx>
59 #include <svl/zforlist.hxx>
60 #include <svx/dialmgr.hxx>
61 #include <toolkit/helper/vclunohelper.hxx>
62 #include <tools/debug.hxx>
63 #include <tools/diagnose_ex.h>
64 #include <vcl/settings.hxx>
65 #include <vcl/svapp.hxx>
66 #include <connectivity/dbtools.hxx>
67 #include <connectivity/dbconversion.hxx>
68 #include <connectivity/sqlnode.hxx>
70 using namespace ::connectivity;
71 using namespace ::svxform;
72 using namespace ::comphelper;
73 using namespace ::svt;
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::sdbc;
77 using namespace ::com::sun::star::sdbcx;
78 using namespace ::com::sun::star::sdb;
79 using namespace ::com::sun::star::beans;
80 using namespace ::com::sun::star::form;
81 using namespace ::dbtools::DBTypeConversion;
82 using namespace ::dbtools;
84 using ::com::sun::star::util::XNumberFormatter;
86 const char INVALIDTEXT[] = "###";
87 const char OBJECTTEXT[] = "<OBJECT>";
90 //= helper
92 namespace
94 LineEnd getModelLineEndSetting( const Reference< XPropertySet >& _rxModel )
96 LineEnd eFormat = LINEEND_LF;
98 try
100 sal_Int16 nLineEndFormat = awt::LineEndFormat::LINE_FEED;
102 Reference< XPropertySetInfo > xPSI;
103 if ( _rxModel.is() )
104 xPSI = _rxModel->getPropertySetInfo();
106 OSL_ENSURE( xPSI.is(), "getModelLineEndSetting: invalid column model!" );
107 if ( xPSI.is() && xPSI->hasPropertyByName( FM_PROP_LINEENDFORMAT ) )
109 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_LINEENDFORMAT ) >>= nLineEndFormat );
111 switch ( nLineEndFormat )
113 case awt::LineEndFormat::CARRIAGE_RETURN: eFormat = LINEEND_CR; break;
114 case awt::LineEndFormat::LINE_FEED: eFormat = LINEEND_LF; break;
115 case awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED: eFormat = LINEEND_CRLF; break;
116 default:
117 OSL_FAIL( "getModelLineEndSetting: what's this?" );
121 catch( const Exception& )
123 TOOLS_WARN_EXCEPTION( "svx", "getModelLineEndSetting" );
125 return eFormat;
130 //= DbGridColumn
133 CellControllerRef DbGridColumn::s_xEmptyController;
136 void DbGridColumn::CreateControl(sal_Int32 _nFieldPos, const Reference< css::beans::XPropertySet >& xField, sal_Int32 nTypeId)
138 Clear();
140 m_nTypeId = static_cast<sal_Int16>(nTypeId);
141 if (xField != m_xField)
143 // initial setting
144 m_xField = xField;
145 xField->getPropertyValue(FM_PROP_FORMATKEY) >>= m_nFormatKey;
146 m_nFieldPos = static_cast<sal_Int16>(_nFieldPos);
147 m_bReadOnly = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISREADONLY));
148 m_bAutoValue = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_AUTOINCREMENT));
149 m_nFieldType = static_cast<sal_Int16>(::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE)));
151 switch (m_nFieldType)
153 case DataType::DATE:
154 case DataType::TIME:
155 case DataType::TIMESTAMP:
156 case DataType::BIT:
157 case DataType::BOOLEAN:
158 case DataType::TINYINT:
159 case DataType::SMALLINT:
160 case DataType::INTEGER:
161 case DataType::BIGINT:
162 case DataType::FLOAT:
163 case DataType::REAL:
164 case DataType::DOUBLE:
165 case DataType::NUMERIC:
166 case DataType::DECIMAL:
167 m_nAlign = css::awt::TextAlign::RIGHT;
168 m_bNumeric = true;
169 break;
170 default:
171 m_nAlign = css::awt::TextAlign::LEFT;
172 break;
176 std::unique_ptr<DbCellControl> pCellControl;
177 if (m_rParent.IsFilterMode())
179 pCellControl.reset(new DbFilterField(m_rParent.getContext(),*this));
181 else
184 switch (nTypeId)
186 case TYPE_CHECKBOX: pCellControl.reset(new DbCheckBox(*this)); break;
187 case TYPE_COMBOBOX: pCellControl.reset(new DbComboBox(*this)); break;
188 case TYPE_CURRENCYFIELD: pCellControl.reset(new DbCurrencyField(*this)); break;
189 case TYPE_DATEFIELD: pCellControl.reset(new DbDateField(*this)); break;
190 case TYPE_LISTBOX: pCellControl.reset(new DbListBox(*this)); break;
191 case TYPE_NUMERICFIELD: pCellControl.reset(new DbNumericField(*this)); break;
192 case TYPE_PATTERNFIELD: pCellControl.reset(new DbPatternField( *this, m_rParent.getContext() )); break;
193 case TYPE_TEXTFIELD: pCellControl.reset(new DbTextField(*this)); break;
194 case TYPE_TIMEFIELD: pCellControl.reset(new DbTimeField(*this)); break;
195 case TYPE_FORMATTEDFIELD: pCellControl.reset(new DbFormattedField(*this)); break;
196 default:
197 OSL_FAIL("DbGridColumn::CreateControl: Unknown Column");
198 return;
202 Reference< XRowSet > xCur;
203 if (m_rParent.getDataSource())
204 xCur.set(Reference< XInterface >(*m_rParent.getDataSource()), UNO_QUERY);
205 // TODO : the cursor wrapper should use an XRowSet interface, too
207 pCellControl->Init( m_rParent.GetDataWindow(), xCur );
209 // now create the control wrapper
210 auto pTempCellControl = pCellControl.get();
211 if (m_rParent.IsFilterMode())
212 m_pCell = new FmXFilterCell(this, std::unique_ptr<DbFilterField>(static_cast<DbFilterField*>(pCellControl.release())));
213 else
215 switch (nTypeId)
217 case TYPE_CHECKBOX: m_pCell = new FmXCheckBoxCell( this, std::move(pCellControl) ); break;
218 case TYPE_LISTBOX: m_pCell = new FmXListBoxCell( this, std::move(pCellControl) ); break;
219 case TYPE_COMBOBOX: m_pCell = new FmXComboBoxCell( this, std::move(pCellControl) ); break;
220 default:
221 m_pCell = new FmXEditCell( this, std::move(pCellControl) );
224 m_pCell->init();
226 impl_toggleScriptManager_nothrow( true );
228 // only if we use have a bound field, we use a controller for displaying the
229 // window in the grid
230 if (m_xField.is())
231 m_xController = pTempCellControl->CreateController();
235 void DbGridColumn::impl_toggleScriptManager_nothrow( bool _bAttach )
239 Reference< container::XChild > xChild( m_xModel, UNO_QUERY_THROW );
240 Reference< script::XEventAttacherManager > xManager( xChild->getParent(), UNO_QUERY_THROW );
241 Reference< container::XIndexAccess > xContainer( xChild->getParent(), UNO_QUERY_THROW );
243 sal_Int32 nIndexInParent( getElementPos( xContainer, m_xModel ) );
245 Reference< XInterface > xCellInterface( *m_pCell, UNO_QUERY );
246 if ( _bAttach )
247 xManager->attach( nIndexInParent, xCellInterface, makeAny( xCellInterface ) );
248 else
249 xManager->detach( nIndexInParent, xCellInterface );
251 catch( const Exception& )
253 DBG_UNHANDLED_EXCEPTION("svx");
257 void DbGridColumn::UpdateFromField(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter)
259 if (FmXFilterCell* pCell = dynamic_cast<FmXFilterCell*>(m_pCell.get()))
260 pCell->Update();
261 else if (pRow && pRow->IsValid() && m_nFieldPos >= 0 && m_pCell.is() && pRow->HasField(m_nFieldPos))
263 dynamic_cast<FmXDataCell&>(*m_pCell).UpdateFromField( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter );
267 bool DbGridColumn::Commit()
269 bool bResult = true;
270 if (!m_bInSave && m_pCell.is())
272 m_bInSave = true;
273 bResult = m_pCell->Commit();
275 // store the data into the model
276 FmXDataCell* pDataCell = dynamic_cast<FmXDataCell*>( m_pCell.get() );
277 if (bResult && pDataCell)
279 Reference< css::form::XBoundComponent > xComp(m_xModel, UNO_QUERY);
280 if (xComp.is())
281 bResult = xComp->commit();
283 m_bInSave = false;
285 return bResult;
288 DbGridColumn::~DbGridColumn()
290 Clear();
293 void DbGridColumn::setModel(const css::uno::Reference< css::beans::XPropertySet >& _xModel)
295 if ( m_pCell.is() )
296 impl_toggleScriptManager_nothrow( false );
298 m_xModel = _xModel;
300 if ( m_pCell.is() )
301 impl_toggleScriptManager_nothrow( true );
305 void DbGridColumn::Clear()
307 if ( m_pCell.is() )
309 impl_toggleScriptManager_nothrow( false );
311 m_pCell->dispose();
312 m_pCell.clear();
315 m_xController = nullptr;
316 m_xField = nullptr;
318 m_nFormatKey = 0;
319 m_nFieldPos = -1;
320 m_bReadOnly = true;
321 m_bAutoValue = false;
322 m_nFieldType = DataType::OTHER;
326 sal_Int16 DbGridColumn::SetAlignment(sal_Int16 _nAlign)
328 if (_nAlign == -1)
329 { // 'Standard'
330 if (m_xField.is())
332 sal_Int32 nType = 0;
333 m_xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nType;
335 switch (nType)
337 case DataType::NUMERIC:
338 case DataType::DECIMAL:
339 case DataType::DOUBLE:
340 case DataType::REAL:
341 case DataType::BIGINT:
342 case DataType::INTEGER:
343 case DataType::SMALLINT:
344 case DataType::TINYINT:
345 case DataType::DATE:
346 case DataType::TIME:
347 case DataType::TIMESTAMP:
348 _nAlign = css::awt::TextAlign::RIGHT;
349 break;
350 case DataType::BIT:
351 case DataType::BOOLEAN:
352 _nAlign = css::awt::TextAlign::CENTER;
353 break;
354 default:
355 _nAlign = css::awt::TextAlign::LEFT;
356 break;
359 else
360 _nAlign = css::awt::TextAlign::LEFT;
363 m_nAlign = _nAlign;
364 if (m_pCell.is() && m_pCell->isAlignedController())
365 m_pCell->AlignControl(m_nAlign);
367 return m_nAlign;
371 sal_Int16 DbGridColumn::SetAlignmentFromModel(sal_Int16 nStandardAlign)
373 Any aAlign( m_xModel->getPropertyValue(FM_PROP_ALIGN));
374 if (aAlign.hasValue())
376 sal_Int16 nTest = sal_Int16();
377 if (aAlign >>= nTest)
378 nStandardAlign = nTest;
380 return SetAlignment(nStandardAlign);
384 void DbGridColumn::setLock(bool _bLock)
386 if (m_bLocked == _bLock)
387 return;
388 m_bLocked = _bLock;
390 // is the column we represent active ?
391 if (m_bHidden)
392 return; // no, it isn't (or at least it shouldn't be ...)
394 if (m_rParent.GetCurColumnId() == m_nId)
396 m_rParent.DeactivateCell();
397 m_rParent.ActivateCell(m_rParent.GetCurRow(), m_rParent.GetCurColumnId());
402 OUString DbGridColumn::GetCellText(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter) const
404 OUString aText;
405 if (m_pCell.is() && dynamic_cast<const FmXFilterCell*>( m_pCell.get() ) != nullptr)
406 return aText;
408 if (!pRow || !pRow->IsValid())
409 aText = INVALIDTEXT;
410 else if (pRow->HasField(m_nFieldPos))
412 aText = GetCellText( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter );
414 return aText;
417 OUString DbGridColumn::GetCellText(const Reference< css::sdb::XColumn >& xField, const Reference< XNumberFormatter >& xFormatter) const
419 OUString aText;
420 if (xField.is())
422 FmXTextCell* pTextCell = dynamic_cast<FmXTextCell*>( m_pCell.get() );
423 if (pTextCell)
424 aText = pTextCell->GetText(xField, xFormatter);
425 else if (m_bObject)
426 aText = OBJECTTEXT;
428 return aText;
431 Reference< css::sdb::XColumn > DbGridColumn::GetCurrentFieldValue() const
433 Reference< css::sdb::XColumn > xField;
434 const DbGridRowRef xRow = m_rParent.GetCurrentRow();
435 if (xRow.is() && xRow->HasField(m_nFieldPos))
437 xField = xRow->GetField(m_nFieldPos).getColumn();
439 return xField;
443 void DbGridColumn::Paint(OutputDevice& rDev,
444 const tools::Rectangle& rRect,
445 const DbGridRow* pRow,
446 const Reference< XNumberFormatter >& xFormatter)
448 bool bEnabled = ( rDev.GetOutDevType() != OUTDEV_WINDOW )
449 || ( static_cast< vcl::Window& >( rDev ).IsEnabled() );
451 FmXDataCell* pDataCell = dynamic_cast<FmXDataCell*>( m_pCell.get() );
452 if (pDataCell)
454 if (!pRow || !pRow->IsValid())
456 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
457 if ( !bEnabled )
458 nStyle |= DrawTextFlags::Disable;
460 rDev.DrawText(rRect, OUString(INVALIDTEXT), nStyle);
462 else if (m_bAutoValue && pRow->IsNew())
464 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter;
465 if ( !bEnabled )
466 nStyle |= DrawTextFlags::Disable;
468 switch (GetAlignment())
470 case css::awt::TextAlign::RIGHT:
471 nStyle |= DrawTextFlags::Right;
472 break;
473 case css::awt::TextAlign::CENTER:
474 nStyle |= DrawTextFlags::Center;
475 break;
476 default:
477 nStyle |= DrawTextFlags::Left;
480 rDev.DrawText(rRect, SvxResId(RID_STR_AUTOFIELD), nStyle);
482 else if (pRow->HasField(m_nFieldPos))
484 pDataCell->PaintFieldToCell(rDev, rRect, pRow->GetField( m_nFieldPos ).getColumn(), xFormatter);
487 else if (!m_pCell.is())
489 if (!pRow || !pRow->IsValid())
491 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
492 if ( !bEnabled )
493 nStyle |= DrawTextFlags::Disable;
495 rDev.DrawText(rRect, OUString(INVALIDTEXT), nStyle);
497 else if (pRow->HasField(m_nFieldPos) && m_bObject)
499 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
500 if ( !bEnabled )
501 nStyle |= DrawTextFlags::Disable;
502 rDev.DrawText(rRect, OUString(OBJECTTEXT), nStyle);
505 else if ( auto pFilterCell = dynamic_cast<FmXFilterCell*>( m_pCell.get() ) )
506 pFilterCell->PaintCell( rDev, rRect );
510 void DbGridColumn::ImplInitWindow( vcl::Window const & rParent, const InitWindowFacet _eInitWhat )
512 if ( m_pCell.is() )
513 m_pCell->ImplInitWindow( rParent, _eInitWhat );
517 //= cell controls
520 DbCellControl::DbCellControl( DbGridColumn& _rColumn )
521 :OPropertyChangeListener(m_aMutex)
522 ,m_bTransparent( false )
523 ,m_bAlignedController( true )
524 ,m_bAccessingValueProperty( false )
525 ,m_rColumn( _rColumn )
526 ,m_pPainter( nullptr )
527 ,m_pWindow( nullptr )
529 Reference< XPropertySet > xColModelProps = _rColumn.getModel();
530 if ( !xColModelProps.is() )
531 return;
533 // if our model's format key changes we want to propagate the new value to our windows
534 m_pModelChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, _rColumn.getModel());
536 // be listener for some common properties
537 implDoPropertyListening( FM_PROP_READONLY, false );
538 implDoPropertyListening( FM_PROP_ENABLED, false );
540 // add as listener for all known "value" properties
541 implDoPropertyListening( FM_PROP_VALUE, false );
542 implDoPropertyListening( FM_PROP_STATE, false );
543 implDoPropertyListening( FM_PROP_TEXT, false );
544 implDoPropertyListening( FM_PROP_EFFECTIVE_VALUE, false );
545 implDoPropertyListening( FM_PROP_SELECT_SEQ, false );
546 implDoPropertyListening( FM_PROP_DATE, false );
547 implDoPropertyListening( FM_PROP_TIME, false );
549 // be listener at the bound field as well
552 Reference< XPropertySetInfo > xPSI( xColModelProps->getPropertySetInfo(), UNO_SET_THROW );
553 if ( xPSI->hasPropertyByName( FM_PROP_BOUNDFIELD ) )
555 Reference< XPropertySet > xField;
556 xColModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
557 if ( xField.is() )
559 m_pFieldChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, xField);
560 m_pFieldChangeBroadcaster->addProperty( FM_PROP_ISREADONLY );
564 catch( const Exception& )
566 TOOLS_WARN_EXCEPTION( "svx", "DbCellControl::doPropertyListening" );
571 void DbCellControl::implDoPropertyListening(const OUString& _rPropertyName, bool _bWarnIfNotExistent)
575 Reference< XPropertySet > xColModelProps = m_rColumn.getModel();
576 Reference< XPropertySetInfo > xPSI;
577 if ( xColModelProps.is() )
578 xPSI = xColModelProps->getPropertySetInfo();
580 DBG_ASSERT( !_bWarnIfNotExistent || ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) ),
581 "DbCellControl::doPropertyListening: no property set info or non-existent property!" );
583 if ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) )
584 m_pModelChangeBroadcaster->addProperty( _rPropertyName );
586 catch( const Exception& )
588 TOOLS_WARN_EXCEPTION( "svx", "DbCellControl::doPropertyListening" );
593 void DbCellControl::doPropertyListening(const OUString& _rPropertyName)
595 implDoPropertyListening( _rPropertyName, true );
598 static void lcl_clearBroadCaster(rtl::Reference<::comphelper::OPropertyChangeMultiplexer>& _pBroadcaster)
600 if ( _pBroadcaster.is() )
602 _pBroadcaster->dispose();
603 _pBroadcaster.clear();
604 // no delete, this is done implicitly
608 DbCellControl::~DbCellControl()
610 lcl_clearBroadCaster(m_pModelChangeBroadcaster);
611 lcl_clearBroadCaster(m_pFieldChangeBroadcaster);
613 m_pWindow.disposeAndClear();
614 m_pPainter.disposeAndClear();
617 void DbCellControl::implValuePropertyChanged( )
619 OSL_ENSURE( !isValuePropertyLocked(),
620 "DbCellControl::implValuePropertyChanged: not to be called with the value property locked!" );
622 if ( m_pWindow )
624 if ( m_rColumn.getModel().is() )
625 updateFromModel( m_rColumn.getModel() );
630 void DbCellControl::implAdjustGenericFieldSetting( const Reference< XPropertySet >& /*_rxModel*/ )
632 // nothing to do here
636 void DbCellControl::_propertyChanged(const PropertyChangeEvent& _rEvent)
638 SolarMutexGuard aGuard;
640 Reference< XPropertySet > xSourceProps( _rEvent.Source, UNO_QUERY );
642 if ( _rEvent.PropertyName == FM_PROP_VALUE
643 || _rEvent.PropertyName == FM_PROP_STATE
644 || _rEvent.PropertyName == FM_PROP_TEXT
645 || _rEvent.PropertyName == FM_PROP_EFFECTIVE_VALUE
646 || _rEvent.PropertyName == FM_PROP_SELECT_SEQ
647 || _rEvent.PropertyName == FM_PROP_DATE
648 || _rEvent.PropertyName == FM_PROP_TIME
650 { // it was one of the known "value" properties
651 if ( !isValuePropertyLocked() )
653 implValuePropertyChanged( );
656 else if ( _rEvent.PropertyName == FM_PROP_READONLY )
658 implAdjustReadOnly( xSourceProps, true);
660 else if ( _rEvent.PropertyName == FM_PROP_ISREADONLY )
662 bool bReadOnly = true;
663 _rEvent.NewValue >>= bReadOnly;
664 m_rColumn.SetReadOnly(bReadOnly);
665 implAdjustReadOnly( xSourceProps, false);
667 else if ( _rEvent.PropertyName == FM_PROP_ENABLED )
669 implAdjustEnabled( xSourceProps );
671 else
672 implAdjustGenericFieldSetting( xSourceProps );
675 bool DbCellControl::Commit()
677 // lock the listening for value property changes
678 lockValueProperty();
679 // commit the content of the control into the model's value property
680 bool bReturn = false;
683 bReturn = commitControl();
685 catch( const Exception& )
687 DBG_UNHANDLED_EXCEPTION("svx");
689 // unlock the listening for value property changes
690 unlockValueProperty();
691 // outta here
692 return bReturn;
695 void DbCellControl::ImplInitWindow( vcl::Window const & rParent, const InitWindowFacet _eInitWhat )
697 vcl::Window* pWindows[] = { m_pPainter, m_pWindow };
699 if (_eInitWhat & InitWindowFacet::WritingMode)
701 for (vcl::Window* pWindow : pWindows)
703 if (pWindow)
704 pWindow->EnableRTL(rParent.IsRTLEnabled());
708 if (_eInitWhat & InitWindowFacet::Font)
710 for (vcl::Window* pWindow : pWindows)
712 if (!pWindow)
713 continue;
715 pWindow->SetZoom(rParent.GetZoom());
717 const StyleSettings& rStyleSettings = pWindow->GetSettings().GetStyleSettings();
718 vcl::Font aFont = rStyleSettings.GetFieldFont();
719 aFont.SetTransparent(isTransparent());
721 if (rParent.IsControlFont())
723 pWindow->SetControlFont(rParent.GetControlFont());
724 aFont.Merge(rParent.GetControlFont());
726 else
727 pWindow->SetControlFont();
729 pWindow->SetZoomedPointFont(*pWindow, aFont); // FIXME RenderContext
733 if ((_eInitWhat & InitWindowFacet::Font) || (_eInitWhat & InitWindowFacet::Foreground))
735 Color aTextColor(rParent.IsControlForeground() ? rParent.GetControlForeground() : rParent.GetTextColor());
737 bool bTextLineColor = rParent.IsTextLineColor();
738 Color aTextLineColor(rParent.GetTextLineColor());
740 for (vcl::Window* pWindow : pWindows)
742 if (pWindow)
744 pWindow->SetTextColor(aTextColor);
745 if (rParent.IsControlForeground())
746 pWindow->SetControlForeground(aTextColor);
748 if (bTextLineColor)
749 pWindow->SetTextLineColor();
750 else
751 pWindow->SetTextLineColor(aTextLineColor);
756 if (!(_eInitWhat & InitWindowFacet::Background))
757 return;
759 if (rParent.IsControlBackground())
761 Color aColor(rParent.GetControlBackground());
762 for (vcl::Window* pWindow : pWindows)
764 if (pWindow)
766 if (isTransparent())
767 pWindow->SetBackground();
768 else
770 pWindow->SetBackground(aColor);
771 pWindow->SetControlBackground(aColor);
773 pWindow->SetFillColor(aColor);
777 else
779 if (m_pPainter)
781 if (isTransparent())
782 m_pPainter->SetBackground();
783 else
784 m_pPainter->SetBackground(rParent.GetBackground());
785 m_pPainter->SetFillColor(rParent.GetFillColor());
788 if (m_pWindow)
790 if (isTransparent())
791 m_pWindow->SetBackground(rParent.GetBackground());
792 else
793 m_pWindow->SetFillColor(rParent.GetFillColor());
798 void DbCellControl::implAdjustReadOnly( const Reference< XPropertySet >& _rxModel,bool i_bReadOnly )
800 DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustReadOnly: not to be called without window!" );
801 DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustReadOnly: invalid model!" );
802 if ( !(m_pWindow && _rxModel.is()) )
803 return;
805 bool bReadOnly = m_rColumn.IsReadOnly();
806 if ( !bReadOnly )
808 _rxModel->getPropertyValue( i_bReadOnly ? OUString(FM_PROP_READONLY) : OUString(FM_PROP_ISREADONLY)) >>= bReadOnly;
810 m_pWindow->SetEditableReadOnly(bReadOnly);
813 void DbCellControl::implAdjustEnabled( const Reference< XPropertySet >& _rxModel )
815 DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustEnabled: not to be called without window!" );
816 DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustEnabled: invalid model!" );
817 if ( m_pWindow && _rxModel.is() )
819 bool bEnable = true;
820 _rxModel->getPropertyValue( FM_PROP_ENABLED ) >>= bEnable;
821 m_pWindow->Enable( bEnable );
825 void DbCellControl::Init(BrowserDataWin& rParent, const Reference< XRowSet >& _rxCursor)
827 ImplInitWindow( rParent, InitWindowFacet::All );
829 if ( m_pWindow )
831 // align the control
832 if ( isAlignedController() )
833 AlignControl( m_rColumn.GetAlignment() );
837 // some other common properties
838 Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW );
839 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
841 if ( xModelPSI->hasPropertyByName( FM_PROP_READONLY ) )
843 implAdjustReadOnly( xModel,true );
846 if ( xModelPSI->hasPropertyByName( FM_PROP_ENABLED ) )
848 implAdjustEnabled( xModel );
851 if ( xModelPSI->hasPropertyByName( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) )
853 sal_Int16 nWheelBehavior = css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY;
854 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) >>= nWheelBehavior );
855 MouseWheelBehaviour nVclSetting = MouseWheelBehaviour::FocusOnly;
856 switch ( nWheelBehavior )
858 case css::awt::MouseWheelBehavior::SCROLL_DISABLED: nVclSetting = MouseWheelBehaviour::Disable; break;
859 case css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY: nVclSetting = MouseWheelBehaviour::FocusOnly; break;
860 case css::awt::MouseWheelBehavior::SCROLL_ALWAYS: nVclSetting = MouseWheelBehaviour::ALWAYS; break;
861 default:
862 OSL_FAIL( "DbCellControl::Init: invalid MouseWheelBehavior!" );
863 break;
866 AllSettings aSettings = m_pWindow->GetSettings();
867 MouseSettings aMouseSettings = aSettings.GetMouseSettings();
868 aMouseSettings.SetWheelBehavior( nVclSetting );
869 aSettings.SetMouseSettings( aMouseSettings );
870 m_pWindow->SetSettings( aSettings, true );
873 catch( const Exception& )
875 DBG_UNHANDLED_EXCEPTION("svx");
878 m_xCursor = _rxCursor;
879 if ( m_rColumn.getModel().is() )
880 updateFromModel( m_rColumn.getModel() );
884 void DbCellControl::SetTextLineColor()
886 if (m_pWindow)
887 m_pWindow->SetTextLineColor();
888 if (m_pPainter)
889 m_pPainter->SetTextLineColor();
893 void DbCellControl::SetTextLineColor(const Color& _rColor)
895 if (m_pWindow)
896 m_pWindow->SetTextLineColor(_rColor);
897 if (m_pPainter)
898 m_pPainter->SetTextLineColor(_rColor);
901 namespace
903 void lcl_implAlign( vcl::Window* _pWindow, WinBits _nAlignmentBit )
905 if (EditControlBase* pControl = dynamic_cast<EditControlBase*>(_pWindow))
907 switch (_nAlignmentBit)
909 case WB_LEFT:
910 pControl->get_widget().set_alignment(TxtAlign::Left);
911 break;
912 case WB_CENTER:
913 pControl->get_widget().set_alignment(TxtAlign::Center);
914 break;
915 case WB_RIGHT:
916 pControl->get_widget().set_alignment(TxtAlign::Right);
917 break;
919 return;
922 WinBits nStyle = _pWindow->GetStyle();
923 nStyle &= ~(WB_LEFT | WB_RIGHT | WB_CENTER);
924 _pWindow->SetStyle( nStyle | _nAlignmentBit );
928 void DbCellControl::AlignControl(sal_Int16 nAlignment)
930 WinBits nAlignmentBit = 0;
931 switch (nAlignment)
933 case css::awt::TextAlign::RIGHT:
934 nAlignmentBit = WB_RIGHT;
935 break;
936 case css::awt::TextAlign::CENTER:
937 nAlignmentBit = WB_CENTER;
938 break;
939 default:
940 nAlignmentBit = WB_LEFT;
941 break;
943 lcl_implAlign( m_pWindow, nAlignmentBit );
944 if ( m_pPainter )
945 lcl_implAlign( m_pPainter, nAlignmentBit );
948 void DbCellControl::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect)
950 m_pPainter->SetSizePixel(rRect.GetSize());
951 m_pPainter->Draw(&rDev, rRect.TopLeft(), DrawFlags::NONE);
954 void DbCellControl::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
956 m_pPainter->SetText( GetFormatText( _rxField, _rxFormatter ) );
957 PaintCell( _rDev, _rRect );
960 double DbCellControl::GetValue(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) const
962 double fValue = 0;
963 if (m_rColumn.IsNumeric())
967 fValue = _rxField->getDouble();
969 catch(const Exception&) { }
971 else
973 bool bSuccess = false;
976 fValue = _rxField->getDouble();
977 bSuccess = true;
979 catch(const Exception&) { }
980 if (!bSuccess)
984 fValue = xFormatter->convertStringToNumber(m_rColumn.GetKey(), _rxField->getString());
986 catch(const Exception&) { }
989 return fValue;
992 void DbCellControl::invalidatedController()
994 m_rColumn.GetParent().refreshController(m_rColumn.GetId(), DbGridControl::GrantControlAccess());
997 // CellModels
999 DbLimitedLengthField::DbLimitedLengthField( DbGridColumn& _rColumn )
1000 :DbCellControl( _rColumn )
1002 doPropertyListening( FM_PROP_MAXTEXTLEN );
1006 void DbLimitedLengthField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1008 DBG_ASSERT( m_pWindow, "DbLimitedLengthField::implAdjustGenericFieldSetting: not to be called without window!" );
1009 DBG_ASSERT( _rxModel.is(), "DbLimitedLengthField::implAdjustGenericFieldSetting: invalid model!" );
1010 if ( m_pWindow && _rxModel.is() )
1012 sal_Int16 nMaxLen = 0;
1013 _rxModel->getPropertyValue( FM_PROP_MAXTEXTLEN ) >>= nMaxLen;
1014 implSetMaxTextLen( nMaxLen );
1018 void DbLimitedLengthField::implSetEffectiveMaxTextLen(sal_Int32 nMaxLen)
1020 dynamic_cast<EditControlBase&>(*m_pWindow).get_widget().set_max_length(nMaxLen);
1021 if (m_pPainter)
1022 dynamic_cast<EditControlBase&>(*m_pPainter).get_widget().set_max_length(nMaxLen);
1025 DbTextField::DbTextField(DbGridColumn& _rColumn)
1026 :DbLimitedLengthField(_rColumn)
1027 ,m_bIsSimpleEdit( true )
1031 DbTextField::~DbTextField( )
1033 m_pPainterImplementation.reset();
1034 m_pEdit.reset();
1037 void DbTextField::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
1039 sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1);
1041 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1043 bool bLeftAlign = true;
1045 // is this a multi-line field?
1046 bool bIsMultiLine = false;
1049 if ( xModel.is() )
1051 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MULTILINE ) >>= bIsMultiLine );
1054 catch( const Exception& )
1056 TOOLS_WARN_EXCEPTION("svx",
1057 "caught an exception while determining the multi-line capabilities!");
1060 m_bIsSimpleEdit = !bIsMultiLine;
1061 if ( bIsMultiLine )
1063 auto xEditControl = VclPtr<MultiLineTextCell>::Create(&rParent);
1064 auto xEditPainter = VclPtr<MultiLineTextCell>::Create(&rParent);
1066 switch (nAlignment)
1068 case awt::TextAlign::RIGHT:
1069 xEditControl->get_widget().set_alignment(TxtAlign::Right);
1070 xEditPainter->get_widget().set_alignment(TxtAlign::Right);
1071 bLeftAlign = false;
1072 break;
1073 case awt::TextAlign::CENTER:
1074 xEditControl->get_widget().set_alignment(TxtAlign::Center);
1075 xEditPainter->get_widget().set_alignment(TxtAlign::Center);
1076 bLeftAlign = false;
1077 break;
1080 m_pWindow = xEditControl;
1081 m_pEdit.reset(new MultiLineEditImplementation(*xEditControl));
1083 m_pPainter = xEditPainter;
1084 m_pPainterImplementation.reset(new MultiLineEditImplementation(*xEditPainter));
1086 else
1088 auto xEditControl = VclPtr<EditControl>::Create(&rParent);
1089 auto xEditPainter = VclPtr<EditControl>::Create(&rParent);
1091 switch (nAlignment)
1093 case awt::TextAlign::RIGHT:
1094 xEditControl->get_widget().set_alignment(TxtAlign::Right);
1095 xEditPainter->get_widget().set_alignment(TxtAlign::Right);
1096 bLeftAlign = false;
1097 break;
1098 case awt::TextAlign::CENTER:
1099 xEditControl->get_widget().set_alignment(TxtAlign::Center);
1100 xEditPainter->get_widget().set_alignment(TxtAlign::Center);
1101 bLeftAlign = false;
1102 break;
1105 m_pWindow = xEditControl;
1106 m_pEdit.reset(new EntryImplementation(*xEditControl));
1108 m_pPainter = xEditPainter;
1109 m_pPainterImplementation.reset(new EntryImplementation(*xEditPainter));
1112 if (bLeftAlign)
1114 // this is so that when getting the focus, the selection is oriented left-to-right
1115 AllSettings aSettings = m_pWindow->GetSettings();
1116 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1117 aStyleSettings.SetSelectionOptions(
1118 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
1119 aSettings.SetStyleSettings(aStyleSettings);
1120 m_pWindow->SetSettings(aSettings);
1123 implAdjustGenericFieldSetting( xModel );
1125 DbLimitedLengthField::Init( rParent, xCursor );
1128 CellControllerRef DbTextField::CreateController() const
1130 return new EditCellController( m_pEdit.get() );
1133 void DbTextField::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1135 if ( m_pPainterImplementation )
1136 m_pPainterImplementation->SetText( GetFormatText( _rxField, _rxFormatter ) );
1138 DbLimitedLengthField::PaintFieldToCell( _rDev, _rRect, _rxField, _rxFormatter );
1141 OUString DbTextField::GetFormatText(const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, const Color** /*ppColor*/)
1143 if (!_rxField.is())
1144 return OUString();
1146 const css::uno::Reference<css::beans::XPropertySet> xPS(_rxField, UNO_QUERY);
1147 FormattedColumnValue fmter( xFormatter, xPS );
1151 return fmter.getFormattedValue();
1153 catch( const Exception& )
1155 DBG_UNHANDLED_EXCEPTION("svx");
1157 return OUString();
1161 void DbTextField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
1163 m_pEdit->SetText( GetFormatText( _rxField, xFormatter ) );
1164 m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1167 void DbTextField::updateFromModel( Reference< XPropertySet > _rxModel )
1169 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTextField::updateFromModel: invalid call!" );
1171 OUString sText;
1172 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
1174 sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen();
1175 if (nMaxTextLen != 0 && sText.getLength() > nMaxTextLen)
1177 sal_Int32 nDiff = sText.getLength() - nMaxTextLen;
1178 sText = sText.replaceAt(sText.getLength() - nDiff,nDiff, OUString());
1182 m_pEdit->SetText( sText );
1183 m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1186 bool DbTextField::commitControl()
1188 OUString aText( m_pEdit->GetText( getModelLineEndSetting( m_rColumn.getModel() ) ) );
1189 // we have to check if the length before we can decide if the value was modified
1190 sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen();
1191 if (nMaxTextLen != 0)
1193 OUString sOldValue;
1194 m_rColumn.getModel()->getPropertyValue( FM_PROP_TEXT ) >>= sOldValue;
1195 // if the new value didn't change we must set the old long value again
1196 if ( sOldValue.getLength() > nMaxTextLen && sOldValue.compareTo(aText,nMaxTextLen) == 0 )
1197 aText = sOldValue;
1199 m_rColumn.getModel()->setPropertyValue( FM_PROP_TEXT, makeAny( aText ) );
1200 return true;
1203 void DbTextField::implSetEffectiveMaxTextLen( sal_Int32 _nMaxLen )
1205 if ( m_pEdit )
1206 m_pEdit->SetMaxTextLen( _nMaxLen );
1207 if ( m_pPainterImplementation )
1208 m_pPainterImplementation->SetMaxTextLen( _nMaxLen );
1211 DbFormattedField::DbFormattedField(DbGridColumn& _rColumn)
1212 :DbLimitedLengthField(_rColumn)
1214 // if our model's format key changes we want to propagate the new value to our windows
1215 doPropertyListening( FM_PROP_FORMATKEY );
1218 DbFormattedField::~DbFormattedField()
1222 void DbFormattedField::Init( BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
1224 sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1);
1226 Reference< css::beans::XPropertySet > xUnoModel = m_rColumn.getModel();
1228 auto xEditControl = VclPtr<FormattedControl>::Create(&rParent, false);
1229 auto xEditPainter = VclPtr<FormattedControl>::Create(&rParent, false);
1231 weld::EntryFormatter& rControlFormatter = xEditControl->get_formatter();
1232 weld::EntryFormatter& rPainterFormatter = xEditPainter->get_formatter();
1234 m_pWindow = xEditControl.get();
1235 m_pPainter = xEditPainter.get();
1237 switch (nAlignment)
1239 case awt::TextAlign::RIGHT:
1240 xEditControl->get_widget().set_alignment(TxtAlign::Right);
1241 xEditPainter->get_widget().set_alignment(TxtAlign::Right);
1242 break;
1243 case awt::TextAlign::CENTER:
1244 xEditControl->get_widget().set_alignment(TxtAlign::Center);
1245 xEditPainter->get_widget().set_alignment(TxtAlign::Center);
1246 break;
1247 default:
1249 // Everything just so that the selection goes from right to left when getting focus
1250 SelectionOptions eOptions = rControlFormatter.GetEntrySelectionOptions();
1251 rControlFormatter.SetEntrySelectionOptions(eOptions | SelectionOptions::ShowFirst);
1252 break;
1256 implAdjustGenericFieldSetting( xUnoModel );
1258 rControlFormatter.SetStrictFormat(false);
1259 rPainterFormatter.SetStrictFormat(false);
1260 // if one allows any formatting, one cannot make an entry check anyway
1261 // (the FormattedField does not support that anyway, only derived classes)
1263 // get the formatter from the uno model
1264 // (I could theoretically also go via the css::util::NumberFormatter, which the cursor would
1265 // surely give me. The problem is that I can not really rely on the fact that the two
1266 // formatters are the same. Clean is the whole thing if I go via the UNO model.)
1267 sal_Int32 nFormatKey = -1;
1269 // let's see if the model has one ...
1270 DBG_ASSERT(::comphelper::hasProperty(FM_PROP_FORMATSSUPPLIER, xUnoModel), "DbFormattedField::Init : invalid UNO model !");
1271 Any aSupplier( xUnoModel->getPropertyValue(FM_PROP_FORMATSSUPPLIER));
1272 if (aSupplier.hasValue())
1274 m_xSupplier.set(aSupplier, css::uno::UNO_QUERY);
1275 if (m_xSupplier.is())
1277 // if we take the supplier from the model, then also the key
1278 Any aFmtKey( xUnoModel->getPropertyValue(FM_PROP_FORMATKEY));
1279 if (aFmtKey.hasValue())
1281 DBG_ASSERT(aFmtKey.getValueType().getTypeClass() == TypeClass_LONG, "DbFormattedField::Init : invalid format key property (no sal_Int32) !");
1282 nFormatKey = ::comphelper::getINT32(aFmtKey);
1284 else
1286 SAL_INFO("svx.fmcomp", "DbFormattedField::Init : my uno-model has no format-key, but a formats supplier !");
1287 // the OFormattedModel which we usually are working with ensures that the model has a format key
1288 // as soon as the form is loaded. Unfortunally this method here is called from within loaded, too.
1289 // So if our LoadListener is called before the LoadListener of the model, this "else case" is
1290 // allowed.
1291 // Of course our property listener for the FormatKey property will notify us if the prop is changed,
1292 // so this here isn't really bad...
1293 nFormatKey = 0;
1298 // No? Maybe the css::form::component::Form behind the cursor?
1299 if (!m_xSupplier.is())
1301 if (xCursor.is())
1302 { // If we take the formatter from the cursor, then also the key from the field to which we are bound
1303 m_xSupplier = getNumberFormats(getConnection(xCursor));
1305 if (m_rColumn.GetField().is())
1306 nFormatKey = ::comphelper::getINT32(m_rColumn.GetField()->getPropertyValue(FM_PROP_FORMATKEY));
1310 SvNumberFormatter* pFormatterUsed = nullptr;
1311 if (m_xSupplier.is())
1313 SvNumberFormatsSupplierObj* pImplementation = comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>(m_xSupplier);
1314 if (pImplementation)
1315 pFormatterUsed = pImplementation->GetNumberFormatter();
1316 else
1317 // Everything is invalid: the supplier is of the wrong type, then we can not
1318 // rely on a standard formatter to know the (possibly non-standard) key.
1319 nFormatKey = -1;
1322 // a standard formatter ...
1323 if (pFormatterUsed == nullptr)
1325 pFormatterUsed = rControlFormatter.StandardFormatter();
1326 DBG_ASSERT(pFormatterUsed != nullptr, "DbFormattedField::Init : no standard formatter given by the numeric field !");
1328 // ... and a standard key
1329 if (nFormatKey == -1)
1330 nFormatKey = 0;
1332 rControlFormatter.SetFormatter(pFormatterUsed);
1333 rPainterFormatter.SetFormatter(pFormatterUsed);
1335 rControlFormatter.SetFormatKey(nFormatKey);
1336 rPainterFormatter.SetFormatKey(nFormatKey);
1338 rControlFormatter.TreatAsNumber(m_rColumn.IsNumeric());
1339 rPainterFormatter.TreatAsNumber(m_rColumn.IsNumeric());
1341 // min and max values
1342 if (m_rColumn.IsNumeric())
1344 bool bClearMin = true;
1345 if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MIN, xUnoModel))
1347 Any aMin( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MIN));
1348 if (aMin.getValueType().getTypeClass() != TypeClass_VOID)
1350 DBG_ASSERT(aMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid min value !");
1351 double dMin = ::comphelper::getDouble(aMin);
1352 rControlFormatter.SetMinValue(dMin);
1353 rPainterFormatter.SetMinValue(dMin);
1354 bClearMin = false;
1357 if (bClearMin)
1359 rControlFormatter.ClearMinValue();
1360 rPainterFormatter.ClearMinValue();
1362 bool bClearMax = true;
1363 if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MAX, xUnoModel))
1365 Any aMax(xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MAX));
1366 if (aMax.getValueType().getTypeClass() != TypeClass_VOID)
1368 DBG_ASSERT(aMax.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid max value !");
1369 double dMax = ::comphelper::getDouble(aMax);
1370 rControlFormatter.SetMaxValue(dMax);
1371 rPainterFormatter.SetMaxValue(dMax);
1372 bClearMax = false;
1375 if (bClearMax)
1377 rControlFormatter.ClearMaxValue();
1378 rPainterFormatter.ClearMaxValue();
1382 // the default value
1383 Any aDefault( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_DEFAULT));
1384 if (aDefault.hasValue())
1385 { // the thing can be a double or a string
1386 switch (aDefault.getValueType().getTypeClass())
1388 case TypeClass_DOUBLE:
1389 if (m_rColumn.IsNumeric())
1391 rControlFormatter.SetDefaultValue(::comphelper::getDouble(aDefault));
1392 rPainterFormatter.SetDefaultValue(::comphelper::getDouble(aDefault));
1394 else
1396 OUString sConverted;
1397 const Color* pDummy;
1398 pFormatterUsed->GetOutputString(::comphelper::getDouble(aDefault), 0, sConverted, &pDummy);
1399 rControlFormatter.SetDefaultText(sConverted);
1400 rPainterFormatter.SetDefaultText(sConverted);
1402 break;
1403 case TypeClass_STRING:
1405 OUString sDefault( ::comphelper::getString(aDefault) );
1406 if (m_rColumn.IsNumeric())
1408 double dVal;
1409 sal_uInt32 nTestFormat(0);
1410 if (pFormatterUsed->IsNumberFormat(sDefault, nTestFormat, dVal))
1412 rControlFormatter.SetDefaultValue(dVal);
1413 rPainterFormatter.SetDefaultValue(dVal);
1416 else
1418 rControlFormatter.SetDefaultText(sDefault);
1419 rPainterFormatter.SetDefaultText(sDefault);
1422 break;
1423 default:
1424 OSL_FAIL( "DbFormattedField::Init: unexpected value type!" );
1425 break;
1428 DbLimitedLengthField::Init( rParent, xCursor );
1431 CellControllerRef DbFormattedField::CreateController() const
1433 return new ::svt::FormattedFieldCellController(static_cast<FormattedControlBase*>(m_pWindow.get()));
1436 void DbFormattedField::_propertyChanged( const PropertyChangeEvent& _rEvent )
1438 if (_rEvent.PropertyName == FM_PROP_FORMATKEY )
1440 sal_Int32 nNewKey = _rEvent.NewValue.hasValue() ? ::comphelper::getINT32(_rEvent.NewValue) : 0;
1442 DBG_ASSERT(m_pWindow && m_pPainter, "DbFormattedField::_propertyChanged : where are my windows ?");
1443 if (m_pWindow)
1444 static_cast<FormattedControlBase*>(m_pWindow.get())->get_formatter().SetFormatKey(nNewKey);
1445 if (m_pPainter)
1446 static_cast<FormattedControlBase*>(m_pPainter.get())->get_formatter().SetFormatKey(nNewKey);
1448 else
1450 DbLimitedLengthField::_propertyChanged( _rEvent );
1454 OUString DbFormattedField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** ppColor)
1456 // no color specification by default
1457 if (ppColor != nullptr)
1458 *ppColor = nullptr;
1460 // NULL value -> empty text
1461 if (!_rxField.is())
1462 return OUString();
1464 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pPainter.get());
1465 weld::EntryFormatter& rPainterFormatter = pControl->get_formatter();
1467 OUString aText;
1470 if (m_rColumn.IsNumeric())
1472 // The IsNumeric at the column says nothing about the class of the used format, but
1473 // about the class of the field bound to the column. So when you bind a FormattedField
1474 // column to a double field and format it as text, m_rColumn.IsNumeric() returns
1475 // sal_True. So that simply means that I can query the contents of the variant using
1476 // getDouble, and then I can leave the rest (the formatting) to the FormattedField.
1477 double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() );
1478 if (_rxField->wasNull())
1479 return aText;
1480 rPainterFormatter.SetValue(dValue);
1482 else
1484 // Here I can not work with a double, since the field can not provide it to me.
1485 // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form.
1486 aText = _rxField->getString();
1487 if (_rxField->wasNull())
1488 return aText;
1489 rPainterFormatter.SetTextFormatted(aText);
1492 catch( const Exception& )
1494 DBG_UNHANDLED_EXCEPTION("svx");
1497 aText = pControl->get_widget().get_text();
1498 if (ppColor != nullptr)
1499 *ppColor = rPainterFormatter.GetLastOutputColor();
1501 return aText;
1504 void DbFormattedField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
1508 FormattedControlBase* pEditControl = static_cast<FormattedControlBase*>(m_pWindow.get());
1509 weld::Entry& rEntry = pEditControl->get_widget();
1510 weld::EntryFormatter& rEditFormatter = pEditControl->get_formatter();
1512 if (!_rxField.is())
1514 // NULL value -> empty text
1515 rEntry.set_text(OUString());
1517 else if (m_rColumn.IsNumeric())
1519 // The IsNumeric at the column says nothing about the class of the used format, but
1520 // about the class of the field bound to the column. So when you bind a FormattedField
1521 // column to a double field and format it as text, m_rColumn.IsNumeric() returns
1522 // sal_True. So that simply means that I can query the contents of the variant using
1523 // getDouble, and then I can leave the rest (the formatting) to the FormattedField.
1524 double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() );
1525 if (_rxField->wasNull())
1526 rEntry.set_text(OUString());
1527 else
1528 rEditFormatter.SetValue(dValue);
1530 else
1532 // Here I can not work with a double, since the field can not provide it to me.
1533 // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form.
1534 OUString sText( _rxField->getString());
1536 rEditFormatter.SetTextFormatted( sText );
1537 rEntry.select_region(0, -1);
1540 catch( const Exception& )
1542 DBG_UNHANDLED_EXCEPTION("svx");
1546 void DbFormattedField::updateFromModel( Reference< XPropertySet > _rxModel )
1548 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFormattedField::updateFromModel: invalid call!" );
1550 FormattedControlBase* pEditControl = static_cast<FormattedControlBase*>(m_pWindow.get());
1551 weld::Entry& rEntry = pEditControl->get_widget();
1552 weld::EntryFormatter& rEditFormatter = pEditControl->get_formatter();
1554 OUString sText;
1555 Any aValue = _rxModel->getPropertyValue( FM_PROP_EFFECTIVE_VALUE );
1556 if ( !aValue.hasValue() || (aValue >>= sText) )
1558 // our effective value is transferred as string
1559 rEditFormatter.SetTextFormatted( sText );
1560 rEntry.select_region(0, -1);
1562 else
1564 double dValue = 0;
1565 aValue >>= dValue;
1566 rEditFormatter.SetValue(dValue);
1570 bool DbFormattedField::commitControl()
1572 Any aNewVal;
1574 FormattedControlBase* pEditControl = static_cast<FormattedControlBase*>(m_pWindow.get());
1575 weld::Entry& rEntry = pEditControl->get_widget();
1576 weld::EntryFormatter& rEditFormatter = pEditControl->get_formatter();
1578 if (m_rColumn.IsNumeric())
1580 if (!rEntry.get_text().isEmpty())
1581 aNewVal <<= rEditFormatter.GetValue();
1582 // an empty string is passed on as void by default, to start with
1584 else
1585 aNewVal <<= rEditFormatter.GetTextValue();
1587 m_rColumn.getModel()->setPropertyValue(FM_PROP_EFFECTIVE_VALUE, aNewVal);
1588 return true;
1591 DbCheckBox::DbCheckBox( DbGridColumn& _rColumn )
1592 :DbCellControl( _rColumn )
1594 setAlignedController( false );
1597 namespace
1599 void setCheckBoxStyle( vcl::Window* _pWindow, bool bMono )
1601 AllSettings aSettings = _pWindow->GetSettings();
1602 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1603 if( bMono )
1604 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::Mono );
1605 else
1606 aStyleSettings.SetOptions( aStyleSettings.GetOptions() & (~StyleSettingsOptions::Mono) );
1607 aSettings.SetStyleSettings( aStyleSettings );
1608 _pWindow->SetSettings( aSettings );
1612 void DbCheckBox::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
1614 setTransparent( true );
1616 m_pWindow = VclPtr<CheckBoxControl>::Create( &rParent );
1617 m_pPainter = VclPtr<CheckBoxControl>::Create( &rParent );
1619 m_pWindow->SetPaintTransparent( true );
1620 m_pPainter->SetPaintTransparent( true );
1622 m_pPainter->SetBackground();
1626 Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW );
1628 sal_Int16 nStyle = awt::VisualEffect::LOOK3D;
1629 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_VISUALEFFECT ) >>= nStyle );
1631 setCheckBoxStyle( m_pWindow, nStyle == awt::VisualEffect::FLAT );
1632 setCheckBoxStyle( m_pPainter, nStyle == awt::VisualEffect::FLAT );
1634 bool bTristate = true;
1635 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_TRISTATE ) >>= bTristate );
1636 static_cast< CheckBoxControl* >( m_pWindow.get() )->EnableTriState( bTristate );
1637 static_cast< CheckBoxControl* >( m_pPainter.get() )->EnableTriState( bTristate );
1639 catch( const Exception& )
1641 DBG_UNHANDLED_EXCEPTION("svx");
1644 DbCellControl::Init( rParent, xCursor );
1647 CellControllerRef DbCheckBox::CreateController() const
1649 return new CheckBoxCellController(static_cast<CheckBoxControl*>(m_pWindow.get()));
1652 static void lcl_setCheckBoxState( const Reference< css::sdb::XColumn >& _rxField,
1653 CheckBoxControl* _pCheckBoxControl )
1655 TriState eState = TRISTATE_INDET;
1656 if (_rxField.is())
1660 bool bValue = _rxField->getBoolean();
1661 if (!_rxField->wasNull())
1662 eState = bValue ? TRISTATE_TRUE : TRISTATE_FALSE;
1664 catch( const Exception& )
1666 DBG_UNHANDLED_EXCEPTION("svx");
1669 _pCheckBoxControl->SetState(eState);
1672 void DbCheckBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
1674 lcl_setCheckBoxState( _rxField, static_cast<CheckBoxControl*>(m_pWindow.get()) );
1677 void DbCheckBox::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect,
1678 const Reference< css::sdb::XColumn >& _rxField,
1679 const Reference< XNumberFormatter >& xFormatter)
1681 CheckBoxControl* pControl = static_cast<CheckBoxControl*>(m_pPainter.get());
1682 lcl_setCheckBoxState( _rxField, pControl );
1684 Size aBoxSize;
1686 switch (rDev.GetOutDevType())
1688 case OUTDEV_WINDOW:
1689 case OUTDEV_VIRDEV:
1690 aBoxSize = pControl->GetBox().get_preferred_size();
1691 break;
1692 case OUTDEV_PRINTER:
1693 case OUTDEV_PDF:
1695 auto nSize = std::min(rRect.GetWidth(), rRect.GetHeight());
1696 aBoxSize = Size(nSize, nSize);
1697 break;
1701 tools::Rectangle aRect(Point(rRect.Left() + ((rRect.GetWidth() - aBoxSize.Width()) / 2),
1702 rRect.Top() + ((rRect.GetHeight() - aBoxSize.Height()) / 2)),
1703 aBoxSize);
1705 DbCellControl::PaintFieldToCell(rDev, aRect, _rxField, xFormatter);
1708 void DbCheckBox::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect)
1710 switch (rDev.GetOutDevType())
1712 case OUTDEV_WINDOW:
1713 case OUTDEV_VIRDEV:
1714 DbCellControl::PaintCell(rDev, rRect);
1715 break;
1716 case OUTDEV_PRINTER:
1717 case OUTDEV_PDF:
1719 TriState eState = static_cast<CheckBoxControl*>(m_pWindow.get())->GetState();
1721 MapMode aResMapMode(MapUnit::Map100thMM);
1722 Size aImageSize = rDev.LogicToPixel(Size(300, 300), aResMapMode);
1723 Size aBrd1Size = rDev.LogicToPixel(Size(20, 20), aResMapMode);
1724 Size aBrd2Size = rDev.LogicToPixel(Size(30, 30), aResMapMode);
1725 int nCheckWidth = rDev.LogicToPixel(Size(20, 20), aResMapMode).Width();
1727 tools::Rectangle aStateRect;
1728 aStateRect.SetLeft(rRect.Left() + ((rRect.GetWidth() - aImageSize.Width()) / 2));
1729 aStateRect.SetTop(rRect.Top() + ((rRect.GetHeight() - aImageSize.Height()) / 2));
1730 aStateRect.SetRight(aStateRect.Left() + aImageSize.Width() - 1);
1731 aStateRect.SetBottom(aStateRect.Top() + aImageSize.Height() - 1);
1733 rDev.Push();
1734 rDev.SetMapMode();
1736 rDev.SetLineColor();
1737 rDev.SetFillColor(COL_BLACK);
1738 rDev.DrawRect(aStateRect);
1739 aStateRect.AdjustLeft(aBrd1Size.Width());
1740 aStateRect.AdjustTop(aBrd1Size.Height());
1741 aStateRect.AdjustRight(-aBrd1Size.Width());
1742 aStateRect.AdjustBottom(-aBrd1Size.Height());
1743 if (eState == TRISTATE_INDET)
1744 rDev.SetFillColor(COL_LIGHTGRAY);
1745 else
1746 rDev.SetFillColor(COL_WHITE);
1747 rDev.DrawRect(aStateRect);
1749 if (eState == TRISTATE_TRUE)
1751 aStateRect.AdjustLeft(aBrd2Size.Width());
1752 aStateRect.AdjustTop(aBrd2Size.Height());
1753 aStateRect.AdjustRight(-aBrd2Size.Width());
1754 aStateRect.AdjustBottom(-aBrd2Size.Height());
1755 Point aPos11(aStateRect.TopLeft());
1756 Point aPos12(aStateRect.BottomRight());
1757 Point aPos21(aStateRect.TopRight());
1758 Point aPos22(aStateRect.BottomLeft());
1759 Point aTempPos11(aPos11);
1760 Point aTempPos12(aPos12);
1761 Point aTempPos21(aPos21);
1762 Point aTempPos22(aPos22);
1763 rDev.SetLineColor(COL_BLACK);
1764 int nDX = 0;
1765 for (int i = 0; i < nCheckWidth; i++)
1767 if ( !(i % 2) )
1769 aTempPos11.setX(aPos11.X() + nDX);
1770 aTempPos12.setX(aPos12.X() + nDX);
1771 aTempPos21.setX(aPos21.X() + nDX);
1772 aTempPos22.setX(aPos22.X() + nDX);
1774 else
1776 nDX++;
1777 aTempPos11.setX(aPos11.X() - nDX);
1778 aTempPos12.setX(aPos12.X() - nDX);
1779 aTempPos21.setX(aPos21.X() - nDX);
1780 aTempPos22.setX(aPos22.X() - nDX);
1782 rDev.DrawLine(aTempPos11, aTempPos12);
1783 rDev.DrawLine(aTempPos21, aTempPos22);
1787 rDev.Pop();
1788 break;
1793 void DbCheckBox::updateFromModel( Reference< XPropertySet > _rxModel )
1795 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCheckBox::updateFromModel: invalid call!" );
1797 sal_Int16 nState = TRISTATE_INDET;
1798 _rxModel->getPropertyValue( FM_PROP_STATE ) >>= nState;
1799 static_cast< CheckBoxControl* >( m_pWindow.get() )->SetState( static_cast< TriState >( nState ) );
1802 bool DbCheckBox::commitControl()
1804 m_rColumn.getModel()->setPropertyValue( FM_PROP_STATE,
1805 makeAny( static_cast<sal_Int16>( static_cast< CheckBoxControl* >( m_pWindow.get() )->GetState() ) ) );
1806 return true;
1809 OUString DbCheckBox::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/)
1811 return OUString();
1814 DbPatternField::DbPatternField( DbGridColumn& _rColumn, const Reference<XComponentContext>& _rContext )
1815 :DbCellControl( _rColumn )
1816 ,m_xContext( _rContext )
1818 doPropertyListening( FM_PROP_LITERALMASK );
1819 doPropertyListening( FM_PROP_EDITMASK );
1820 doPropertyListening( FM_PROP_STRICTFORMAT );
1823 void DbPatternField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1825 DBG_ASSERT( m_pWindow, "DbPatternField::implAdjustGenericFieldSetting: not to be called without window!" );
1826 DBG_ASSERT( _rxModel.is(), "DbPatternField::implAdjustGenericFieldSetting: invalid model!" );
1827 if ( !m_pWindow || !_rxModel.is() )
1828 return;
1830 OUString aLitMask;
1831 OUString aEditMask;
1832 bool bStrict = false;
1834 _rxModel->getPropertyValue( FM_PROP_LITERALMASK ) >>= aLitMask;
1835 _rxModel->getPropertyValue( FM_PROP_EDITMASK ) >>= aEditMask;
1836 _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) >>= bStrict;
1838 OString aAsciiEditMask(OUStringToOString(aEditMask, RTL_TEXTENCODING_ASCII_US));
1840 weld::PatternFormatter& rEditFormatter = static_cast<PatternControl*>(m_pWindow.get())->get_formatter();
1841 rEditFormatter.SetMask(aAsciiEditMask, aLitMask);
1842 rEditFormatter.SetStrictFormat(bStrict);
1844 weld::PatternFormatter& rPaintFormatter = static_cast<PatternControl*>(m_pPainter.get())->get_formatter();
1845 rPaintFormatter.SetMask(aAsciiEditMask, aLitMask);
1846 rPaintFormatter.SetStrictFormat(bStrict);
1849 void DbPatternField::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
1851 m_rColumn.SetAlignmentFromModel(-1);
1853 m_pWindow = VclPtr<PatternControl>::Create(&rParent);
1854 m_pPainter= VclPtr<PatternControl>::Create(&rParent);
1856 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1857 implAdjustGenericFieldSetting( xModel );
1859 DbCellControl::Init( rParent, xCursor );
1862 CellControllerRef DbPatternField::CreateController() const
1864 return new EditCellController(static_cast<PatternControl*>(m_pWindow.get()));
1867 OUString DbPatternField::impl_formatText( const OUString& _rText )
1869 weld::PatternFormatter& rPaintFormatter = static_cast<PatternControl*>(m_pPainter.get())->get_formatter();
1870 rPaintFormatter.get_widget().set_text(_rText);
1871 rPaintFormatter.ReformatAll();
1872 return rPaintFormatter.get_widget().get_text();
1875 OUString DbPatternField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/)
1877 bool bIsForPaint = _rxField != m_rColumn.GetField();
1878 ::std::unique_ptr< FormattedColumnValue >& rpFormatter = bIsForPaint ? m_pPaintFormatter : m_pValueFormatter;
1880 if (!rpFormatter)
1882 rpFormatter = std::make_unique< FormattedColumnValue> (
1883 m_xContext, getCursor(), Reference< XPropertySet >( _rxField, UNO_QUERY ) );
1884 OSL_ENSURE(rpFormatter, "DbPatternField::Init: no value formatter!");
1886 else
1887 OSL_ENSURE( rpFormatter->getColumn() == _rxField, "DbPatternField::GetFormatText: my value formatter is working for another field ...!" );
1888 // re-creating the value formatter here every time would be quite expensive ...
1890 OUString sText;
1891 if (rpFormatter)
1892 sText = rpFormatter->getFormattedValue();
1894 return impl_formatText( sText );
1897 void DbPatternField::UpdateFromField( const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1899 weld::Entry& rEntry = static_cast<PatternControl*>(m_pWindow.get())->get_widget();
1900 rEntry.set_text(GetFormatText(_rxField, _rxFormatter));
1901 rEntry.select_region(-1, 0);
1904 void DbPatternField::updateFromModel( Reference< XPropertySet > _rxModel )
1906 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbPatternField::updateFromModel: invalid call!" );
1908 OUString sText;
1909 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
1911 weld::Entry& rEntry = static_cast<PatternControl*>(m_pWindow.get())->get_widget();
1912 rEntry.set_text(impl_formatText(sText));
1913 rEntry.select_region(-1, 0);
1916 bool DbPatternField::commitControl()
1918 weld::Entry& rEntry = static_cast<PatternControl*>(m_pWindow.get())->get_widget();
1919 m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, makeAny(rEntry.get_text()));
1920 return true;
1923 DbSpinField::DbSpinField( DbGridColumn& _rColumn, sal_Int16 _nStandardAlign )
1924 :DbCellControl( _rColumn )
1925 ,m_nStandardAlign( _nStandardAlign )
1929 void DbSpinField::Init(BrowserDataWin& _rParent, const Reference< XRowSet >& _rxCursor)
1931 m_rColumn.SetAlignmentFromModel( m_nStandardAlign );
1933 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1935 // determine if we need a spinbutton version
1936 bool bSpinButton(false);
1937 if ( ::comphelper::getBOOL( xModel->getPropertyValue( FM_PROP_SPIN ) ) )
1938 bSpinButton = true;
1939 // create the fields
1940 m_pWindow = createField( &_rParent, bSpinButton, xModel );
1941 m_pPainter = createField( &_rParent, bSpinButton, xModel );
1943 // adjust all other settings which depend on the property values
1944 implAdjustGenericFieldSetting( xModel );
1946 // call the base class
1947 DbCellControl::Init( _rParent, _rxCursor );
1950 CellControllerRef DbSpinField::CreateController() const
1952 return new ::svt::FormattedFieldCellController(static_cast<FormattedControlBase*>(m_pWindow.get()));
1955 DbNumericField::DbNumericField( DbGridColumn& _rColumn )
1956 :DbSpinField( _rColumn )
1958 doPropertyListening( FM_PROP_DECIMAL_ACCURACY );
1959 doPropertyListening( FM_PROP_VALUEMIN );
1960 doPropertyListening( FM_PROP_VALUEMAX );
1961 doPropertyListening( FM_PROP_VALUESTEP );
1962 doPropertyListening( FM_PROP_STRICTFORMAT );
1963 doPropertyListening( FM_PROP_SHOWTHOUSANDSEP );
1966 void DbNumericField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1968 DBG_ASSERT( m_pWindow, "DbNumericField::implAdjustGenericFieldSetting: not to be called without window!" );
1969 DBG_ASSERT( _rxModel.is(), "DbNumericField::implAdjustGenericFieldSetting: invalid model!" );
1970 if ( !m_pWindow || !_rxModel.is() )
1971 return;
1973 sal_Int32 nMin = static_cast<sal_Int32>(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) ));
1974 sal_Int32 nMax = static_cast<sal_Int32>(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) ));
1975 sal_Int32 nStep = static_cast<sal_Int32>(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) ));
1976 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
1977 sal_Int16 nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) );
1978 bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) );
1980 Formatter& rEditFormatter = static_cast<FormattedControlBase*>(m_pWindow.get())->get_formatter();
1981 rEditFormatter.SetMinValue(nMin);
1982 rEditFormatter.SetMaxValue(nMax);
1983 rEditFormatter.SetSpinSize(nStep);
1984 rEditFormatter.SetStrictFormat(bStrict);
1986 Formatter& rPaintFormatter = static_cast<FormattedControlBase*>(m_pPainter.get())->get_formatter();
1987 rPaintFormatter.SetMinValue(nMin);
1988 rPaintFormatter.SetMaxValue(nMax);
1989 rPaintFormatter.SetStrictFormat(bStrict);
1991 // give a formatter to the field and the painter;
1992 // test first if I can get from the service behind a connection
1993 Reference< css::util::XNumberFormatsSupplier > xSupplier;
1994 Reference< XRowSet > xForm;
1995 if ( m_rColumn.GetParent().getDataSource() )
1996 xForm.set( Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY );
1997 if ( xForm.is() )
1998 xSupplier = getNumberFormats( getConnection( xForm ), true );
1999 SvNumberFormatter* pFormatterUsed = nullptr;
2000 if ( xSupplier.is() )
2002 SvNumberFormatsSupplierObj* pImplementation = comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>( xSupplier );
2003 pFormatterUsed = pImplementation ? pImplementation->GetNumberFormatter() : nullptr;
2005 if ( nullptr == pFormatterUsed )
2006 { // the cursor didn't lead to success -> standard
2007 pFormatterUsed = rEditFormatter.StandardFormatter();
2008 DBG_ASSERT( pFormatterUsed != nullptr, "DbNumericField::implAdjustGenericFieldSetting: no standard formatter given by the numeric field !" );
2010 rEditFormatter.SetFormatter( pFormatterUsed );
2011 rPaintFormatter.SetFormatter( pFormatterUsed );
2013 // and then generate a format which has the desired length after the decimal point, etc.
2014 LanguageType aAppLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType();
2015 OUString sFormatString = pFormatterUsed->GenerateFormat(0, aAppLanguage, bThousand, false, nScale);
2017 rEditFormatter.SetFormat( sFormatString, aAppLanguage );
2018 rPaintFormatter.SetFormat( sFormatString, aAppLanguage );
2021 VclPtr<svt::ControlBase> DbNumericField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference<XPropertySet>& /*rxModel*/)
2023 return VclPtr<DoubleNumericControl>::Create(pParent, bSpinButton);
2026 namespace
2028 OUString lcl_setFormattedNumeric_nothrow( FormattedControlBase& _rField, const DbCellControl& _rControl,
2029 const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
2031 OUString sValue;
2032 if ( _rxField.is() )
2036 double fValue = _rControl.GetValue( _rxField, _rxFormatter );
2037 if ( !_rxField->wasNull() )
2039 _rField.get_formatter().SetValue(fValue);
2040 sValue = _rField.get_widget().get_text();
2043 catch( const Exception& )
2045 DBG_UNHANDLED_EXCEPTION("svx");
2048 return sValue;
2052 OUString DbNumericField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, const Color** /*ppColor*/)
2054 return lcl_setFormattedNumeric_nothrow(dynamic_cast<FormattedControlBase&>(*m_pPainter), *this, _rxField, _rxFormatter);
2057 void DbNumericField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter)
2059 lcl_setFormattedNumeric_nothrow(dynamic_cast<FormattedControlBase&>(*m_pWindow), *this, _rxField, _rxFormatter);
2062 void DbNumericField::updateFromModel( Reference< XPropertySet > _rxModel )
2064 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbNumericField::updateFromModel: invalid call!" );
2066 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2068 double dValue = 0;
2069 if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue )
2071 Formatter& rFormatter = pControl->get_formatter();
2072 rFormatter.SetValue(dValue);
2074 else
2075 pControl->get_widget().set_text(OUString());
2078 bool DbNumericField::commitControl()
2080 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2081 OUString aText(pControl->get_widget().get_text());
2082 Any aVal;
2084 if (!aText.isEmpty()) // not empty
2086 Formatter& rFormatter = pControl->get_formatter();
2087 double fValue = rFormatter.GetValue();
2088 aVal <<= fValue;
2090 m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal);
2091 return true;
2094 DbCurrencyField::DbCurrencyField(DbGridColumn& _rColumn)
2095 :DbSpinField( _rColumn )
2097 doPropertyListening( FM_PROP_DECIMAL_ACCURACY );
2098 doPropertyListening( FM_PROP_VALUEMIN );
2099 doPropertyListening( FM_PROP_VALUEMAX );
2100 doPropertyListening( FM_PROP_VALUESTEP );
2101 doPropertyListening( FM_PROP_STRICTFORMAT );
2102 doPropertyListening( FM_PROP_SHOWTHOUSANDSEP );
2103 doPropertyListening( FM_PROP_CURRENCYSYMBOL );
2106 void DbCurrencyField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2108 DBG_ASSERT( m_pWindow, "DbCurrencyField::implAdjustGenericFieldSetting: not to be called without window!" );
2109 DBG_ASSERT( _rxModel.is(), "DbCurrencyField::implAdjustGenericFieldSetting: invalid model!" );
2110 if ( !m_pWindow || !_rxModel.is() )
2111 return;
2113 sal_Int16 nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) );
2114 double nMin = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) );
2115 double nMax = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) );
2116 double nStep = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) );
2117 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2118 bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) );
2119 OUString aStr( getString( _rxModel->getPropertyValue(FM_PROP_CURRENCYSYMBOL ) ) );
2121 Formatter& rEditFormatter = static_cast<FormattedControlBase*>(m_pWindow.get())->get_formatter();
2122 rEditFormatter.SetDecimalDigits(nScale);
2123 rEditFormatter.SetMinValue(nMin);
2124 rEditFormatter.SetMaxValue(nMax);
2125 rEditFormatter.SetSpinSize(nStep);
2126 rEditFormatter.SetStrictFormat(bStrict);
2127 weld::LongCurrencyFormatter& rCurrencyEditFormatter = static_cast<weld::LongCurrencyFormatter&>(rEditFormatter);
2128 rCurrencyEditFormatter.SetUseThousandSep(bThousand);
2129 rCurrencyEditFormatter.SetCurrencySymbol(aStr);
2131 Formatter& rPaintFormatter = static_cast<FormattedControlBase*>(m_pPainter.get())->get_formatter();
2132 rPaintFormatter.SetDecimalDigits(nScale);
2133 rPaintFormatter.SetMinValue(nMin);
2134 rPaintFormatter.SetMaxValue(nMax);
2135 rPaintFormatter.SetStrictFormat(bStrict);
2136 weld::LongCurrencyFormatter& rPaintCurrencyFormatter = static_cast<weld::LongCurrencyFormatter&>(rPaintFormatter);
2137 rPaintCurrencyFormatter.SetUseThousandSep(bThousand);
2138 rPaintCurrencyFormatter.SetCurrencySymbol(aStr);
2141 VclPtr<svt::ControlBase> DbCurrencyField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference< XPropertySet >& /*rxModel*/)
2143 return VclPtr<LongCurrencyControl>::Create(pParent, bSpinButton);
2146 namespace
2148 OUString lcl_setFormattedCurrency_nothrow( FormattedControlBase& _rField, const DbCurrencyField& _rControl,
2149 const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
2151 OUString sValue;
2152 if ( _rxField.is() )
2156 double fValue = _rControl.GetValue( _rxField, _rxFormatter );
2157 if ( !_rxField->wasNull() )
2159 _rField.get_formatter().SetValue(fValue);
2160 sValue = _rField.get_widget().get_text();
2163 catch( const Exception& )
2165 DBG_UNHANDLED_EXCEPTION("svx");
2168 return sValue;
2172 OUString DbCurrencyField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, const Color** /*ppColor*/)
2174 return lcl_setFormattedCurrency_nothrow(dynamic_cast<FormattedControlBase&>(*m_pPainter), *this, _rxField, _rxFormatter);
2177 void DbCurrencyField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter)
2179 lcl_setFormattedCurrency_nothrow(dynamic_cast<FormattedControlBase&>(*m_pWindow), *this, _rxField, _rxFormatter);
2182 void DbCurrencyField::updateFromModel( Reference< XPropertySet > _rxModel )
2184 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCurrencyField::updateFromModel: invalid call!" );
2186 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2188 double dValue = 0;
2189 if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue )
2191 Formatter& rFormatter = pControl->get_formatter();
2192 rFormatter.SetValue(dValue);
2194 else
2195 pControl->get_widget().set_text(OUString());
2198 bool DbCurrencyField::commitControl()
2200 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2201 OUString aText(pControl->get_widget().get_text());
2202 Any aVal;
2204 if (!aText.isEmpty()) // not empty
2206 Formatter& rFormatter = pControl->get_formatter();
2207 double fValue = rFormatter.GetValue();
2208 aVal <<= fValue;
2210 m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal);
2211 return true;
2214 DbDateField::DbDateField( DbGridColumn& _rColumn )
2215 :DbSpinField( _rColumn )
2217 doPropertyListening( FM_PROP_DATEFORMAT );
2218 doPropertyListening( FM_PROP_DATEMIN );
2219 doPropertyListening( FM_PROP_DATEMAX );
2220 doPropertyListening( FM_PROP_STRICTFORMAT );
2221 doPropertyListening( FM_PROP_DATE_SHOW_CENTURY );
2224 VclPtr<svt::ControlBase> DbDateField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference< XPropertySet >& rxModel)
2226 // check if there is a DropDown property set to TRUE
2227 bool bDropDown = !hasProperty( FM_PROP_DROPDOWN, rxModel )
2228 || getBOOL( rxModel->getPropertyValue( FM_PROP_DROPDOWN ) );
2229 // given the apparent inability to set a custom up/down action for a gtk
2230 // spinbutton to have different up/down dates depending on the zone the
2231 // mouse is in, show the dropdown calendar for both the spin or dropdown case
2232 return VclPtr<DateControl>::Create(pParent, bSpinButton || bDropDown);
2235 void DbDateField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2237 DBG_ASSERT( m_pWindow, "DbDateField::implAdjustGenericFieldSetting: not to be called without window!" );
2238 DBG_ASSERT( _rxModel.is(), "DbDateField::implAdjustGenericFieldSetting: invalid model!" );
2239 if ( !m_pWindow || !_rxModel.is() )
2240 return;
2242 sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_DATEFORMAT ) );
2243 util::Date aMin;
2244 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMIN ) >>= aMin );
2245 util::Date aMax;
2246 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMAX ) >>= aMax );
2247 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2249 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2250 weld::DateFormatter& rControlFormatter = static_cast<weld::DateFormatter&>(pControl->get_formatter());
2252 FormattedControlBase* pPainter = static_cast<FormattedControlBase*>(m_pPainter.get());
2253 weld::DateFormatter& rPainterFormatter = static_cast<weld::DateFormatter&>(pPainter->get_formatter());
2255 Any aCentury = _rxModel->getPropertyValue( FM_PROP_DATE_SHOW_CENTURY );
2256 if ( aCentury.getValueType().getTypeClass() != TypeClass_VOID )
2258 bool bShowDateCentury = getBOOL( aCentury );
2260 rControlFormatter.SetShowDateCentury(bShowDateCentury);
2261 rPainterFormatter.SetShowDateCentury(bShowDateCentury);
2264 rControlFormatter.SetExtDateFormat( static_cast<ExtDateFieldFormat>(nFormat) );
2265 rControlFormatter.SetMin( aMin );
2266 rControlFormatter.SetMax( aMax );
2267 rControlFormatter.SetStrictFormat( bStrict );
2268 rControlFormatter.EnableEmptyField( true );
2270 rPainterFormatter.SetExtDateFormat( static_cast<ExtDateFieldFormat>(nFormat) );
2271 rPainterFormatter.SetMin( aMin );
2272 rPainterFormatter.SetMax( aMax );
2273 rPainterFormatter.SetStrictFormat( bStrict );
2274 rPainterFormatter.EnableEmptyField( true );
2277 namespace
2279 OUString lcl_setFormattedDate_nothrow(DateControl& _rField, const Reference<XColumn>& _rxField)
2281 OUString sDate;
2282 if ( _rxField.is() )
2286 css::util::Date aValue = _rxField->getDate();
2287 if (!_rxField->wasNull())
2289 _rField.SetDate(::Date(aValue.Day, aValue.Month, aValue.Year));
2290 sDate = _rField.get_widget().get_text();
2293 catch( const Exception& )
2295 DBG_UNHANDLED_EXCEPTION("svx");
2298 return sDate;
2302 OUString DbDateField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/)
2304 return lcl_setFormattedDate_nothrow(*static_cast<DateControl*>(m_pPainter.get()), _rxField);
2307 void DbDateField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
2309 lcl_setFormattedDate_nothrow(*static_cast<DateControl*>(m_pWindow.get()), _rxField);
2312 void DbDateField::updateFromModel( Reference< XPropertySet > _rxModel )
2314 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbDateField::updateFromModel: invalid call!" );
2316 DateControl* pControl = static_cast<DateControl*>(m_pWindow.get());
2318 util::Date aDate;
2319 if ( _rxModel->getPropertyValue( FM_PROP_DATE ) >>= aDate )
2320 pControl->SetDate(::Date(aDate));
2321 else
2322 pControl->get_widget().set_text(OUString());
2325 bool DbDateField::commitControl()
2327 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2328 OUString aText(pControl->get_widget().get_text());
2329 Any aVal;
2331 if (!aText.isEmpty()) // not empty
2333 weld::DateFormatter& rControlFormatter = static_cast<weld::DateFormatter&>(pControl->get_formatter());
2334 aVal <<= rControlFormatter.GetDate().GetUNODate();
2337 m_rColumn.getModel()->setPropertyValue(FM_PROP_DATE, aVal);
2338 return true;
2341 DbTimeField::DbTimeField( DbGridColumn& _rColumn )
2342 :DbSpinField( _rColumn, css::awt::TextAlign::LEFT )
2344 doPropertyListening( FM_PROP_TIMEFORMAT );
2345 doPropertyListening( FM_PROP_TIMEMIN );
2346 doPropertyListening( FM_PROP_TIMEMAX );
2347 doPropertyListening( FM_PROP_STRICTFORMAT );
2350 VclPtr<svt::ControlBase> DbTimeField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference< XPropertySet >& /*rxModel*/ )
2352 return VclPtr<TimeControl>::Create(pParent, bSpinButton);
2355 void DbTimeField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2357 DBG_ASSERT( m_pWindow, "DbTimeField::implAdjustGenericFieldSetting: not to be called without window!" );
2358 DBG_ASSERT( _rxModel.is(), "DbTimeField::implAdjustGenericFieldSetting: invalid model!" );
2359 if ( !m_pWindow || !_rxModel.is() )
2360 return;
2362 sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_TIMEFORMAT ) );
2363 util::Time aMin;
2364 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMIN ) >>= aMin );
2365 util::Time aMax;
2366 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMAX ) >>= aMax );
2367 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2369 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2370 weld::TimeFormatter& rControlFormatter = static_cast<weld::TimeFormatter&>(pControl->get_formatter());
2372 rControlFormatter.SetExtFormat(static_cast<ExtTimeFieldFormat>(nFormat));
2373 rControlFormatter.SetMin(aMin);
2374 rControlFormatter.SetMax(aMax);
2375 rControlFormatter.SetStrictFormat(bStrict);
2376 rControlFormatter.EnableEmptyField(true);
2378 FormattedControlBase* pPainter = static_cast<FormattedControlBase*>(m_pPainter.get());
2379 weld::TimeFormatter& rPainterFormatter = static_cast<weld::TimeFormatter&>(pPainter->get_formatter());
2381 rPainterFormatter.SetExtFormat(static_cast<ExtTimeFieldFormat>(nFormat));
2382 rPainterFormatter.SetMin(aMin);
2383 rPainterFormatter.SetMax(aMax);
2384 rPainterFormatter.SetStrictFormat(bStrict);
2385 rPainterFormatter.EnableEmptyField(true);
2388 namespace
2390 OUString lcl_setFormattedTime_nothrow(TimeControl& _rField, const Reference<XColumn>& _rxField)
2392 OUString sTime;
2393 if ( _rxField.is() )
2397 css::util::Time aValue = _rxField->getTime();
2398 if (!_rxField->wasNull())
2400 static_cast<weld::TimeFormatter&>(_rField.get_formatter()).SetTime( ::tools::Time( aValue ) );
2401 sTime = _rField.get_widget().get_text();
2404 catch( const Exception& )
2406 DBG_UNHANDLED_EXCEPTION("svx");
2409 return sTime;
2413 OUString DbTimeField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/)
2415 return lcl_setFormattedTime_nothrow(*static_cast<TimeControl*>(m_pPainter.get()), _rxField);
2418 void DbTimeField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
2420 lcl_setFormattedTime_nothrow(*static_cast<TimeControl*>(m_pWindow.get()), _rxField);
2423 void DbTimeField::updateFromModel( Reference< XPropertySet > _rxModel )
2425 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTimeField::updateFromModel: invalid call!" );
2427 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2428 weld::TimeFormatter& rControlFormatter = static_cast<weld::TimeFormatter&>(pControl->get_formatter());
2430 util::Time aTime;
2431 if ( _rxModel->getPropertyValue( FM_PROP_TIME ) >>= aTime )
2432 rControlFormatter.SetTime(::tools::Time(aTime));
2433 else
2434 pControl->get_widget().set_text(OUString());
2437 bool DbTimeField::commitControl()
2439 FormattedControlBase* pControl = static_cast<FormattedControlBase*>(m_pWindow.get());
2440 OUString aText(pControl->get_widget().get_text());
2441 Any aVal;
2443 if (!aText.isEmpty()) // not empty
2445 weld::TimeFormatter& rControlFormatter = static_cast<weld::TimeFormatter&>(pControl->get_formatter());
2446 aVal <<= rControlFormatter.GetTime().GetUNOTime();
2449 m_rColumn.getModel()->setPropertyValue(FM_PROP_TIME, aVal);
2450 return true;
2453 DbComboBox::DbComboBox(DbGridColumn& _rColumn)
2454 :DbCellControl(_rColumn)
2456 setAlignedController( false );
2458 doPropertyListening( FM_PROP_STRINGITEMLIST );
2459 doPropertyListening( FM_PROP_LINECOUNT );
2462 void DbComboBox::_propertyChanged( const PropertyChangeEvent& _rEvent )
2464 if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST )
2466 SetList(_rEvent.NewValue);
2468 else
2470 DbCellControl::_propertyChanged( _rEvent ) ;
2474 void DbComboBox::SetList(const Any& rItems)
2476 ComboBoxControl* pField = static_cast<ComboBoxControl*>(m_pWindow.get());
2477 weld::ComboBox& rComboBox = pField->get_widget();
2478 rComboBox.clear();
2480 css::uno::Sequence<OUString> aTest;
2481 if (rItems >>= aTest)
2483 for (const OUString& rString : std::as_const(aTest))
2484 rComboBox.append_text(rString);
2486 // tell the grid control that this controller is invalid and has to be re-initialized
2487 invalidatedController();
2491 void DbComboBox::implAdjustGenericFieldSetting(const Reference<XPropertySet>&)
2493 // we no longer pay attention to FM_PROP_LINECOUNT
2496 void DbComboBox::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
2498 m_rColumn.SetAlignmentFromModel(css::awt::TextAlign::LEFT);
2500 m_pWindow = VclPtr<ComboBoxControl>::Create( &rParent );
2502 // selection from right to left
2503 AllSettings aSettings = m_pWindow->GetSettings();
2504 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2505 aStyleSettings.SetSelectionOptions(
2506 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2507 aSettings.SetStyleSettings(aStyleSettings);
2508 m_pWindow->SetSettings(aSettings, true);
2510 // some initial properties
2511 Reference< XPropertySet > xModel(m_rColumn.getModel());
2512 SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) );
2513 implAdjustGenericFieldSetting( xModel );
2515 DbCellControl::Init( rParent, xCursor );
2518 CellControllerRef DbComboBox::CreateController() const
2520 return new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2523 OUString DbComboBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, const Color** /*ppColor*/)
2525 const css::uno::Reference<css::beans::XPropertySet> xPS(_rxField, UNO_QUERY);
2526 ::dbtools::FormattedColumnValue fmter( xFormatter, xPS );
2528 return fmter.getFormattedValue();
2531 void DbComboBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
2533 ComboBoxControl* pControl = static_cast<ComboBoxControl*>(m_pWindow.get());
2534 pControl->get_widget().set_entry_text(GetFormatText(_rxField, xFormatter));
2537 void DbComboBox::updateFromModel( Reference< XPropertySet > _rxModel )
2539 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbComboBox::updateFromModel: invalid call!" );
2541 OUString sText;
2542 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
2544 ComboBoxControl* pControl = static_cast<ComboBoxControl*>(m_pWindow.get());
2545 weld::ComboBox& rComboBox = pControl->get_widget();
2547 OUString sOldActive = rComboBox.get_active_text();
2548 rComboBox.set_entry_text(sText);
2549 rComboBox.select_entry_region(0, -1);
2551 if (sOldActive != rComboBox.get_active_text())
2552 pControl->TriggerAuxModify();
2555 bool DbComboBox::commitControl()
2557 ComboBoxControl* pControl = static_cast<ComboBoxControl*>(m_pWindow.get());
2558 weld::ComboBox& rComboBox = pControl->get_widget();
2559 OUString aText(rComboBox.get_active_text());
2560 m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, makeAny(aText));
2561 return true;
2565 DbListBox::DbListBox(DbGridColumn& _rColumn)
2566 :DbCellControl(_rColumn)
2567 ,m_bBound(false)
2569 setAlignedController( false );
2571 doPropertyListening( FM_PROP_STRINGITEMLIST );
2572 doPropertyListening( FM_PROP_LINECOUNT );
2575 void DbListBox::_propertyChanged( const css::beans::PropertyChangeEvent& _rEvent )
2577 if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST )
2579 SetList(_rEvent.NewValue);
2581 else
2583 DbCellControl::_propertyChanged( _rEvent ) ;
2587 void DbListBox::SetList(const Any& rItems)
2589 ListBoxControl* pField = static_cast<ListBoxControl*>(m_pWindow.get());
2591 weld::ComboBox& rFieldList = pField->get_widget();
2593 rFieldList.clear();
2594 m_bBound = false;
2596 css::uno::Sequence<OUString> aTest;
2597 if (!(rItems >>= aTest))
2598 return;
2600 if (aTest.hasElements())
2602 for (const OUString& rString : std::as_const(aTest))
2603 rFieldList.append_text(rString);
2605 m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList;
2606 m_bBound = m_aValueList.hasElements();
2608 // tell the grid control that this controller is invalid and has to be re-initialized
2609 invalidatedController();
2613 void DbListBox::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
2615 m_rColumn.SetAlignment(css::awt::TextAlign::LEFT);
2617 m_pWindow = VclPtr<ListBoxControl>::Create( &rParent );
2619 // some initial properties
2620 Reference< XPropertySet > xModel( m_rColumn.getModel() );
2621 SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) );
2622 implAdjustGenericFieldSetting( xModel );
2624 DbCellControl::Init( rParent, xCursor );
2627 void DbListBox::implAdjustGenericFieldSetting( const Reference< XPropertySet >& /*rxModel*/ )
2629 // ignore FM_PROP_LINECOUNT
2632 CellControllerRef DbListBox::CreateController() const
2634 return new ListBoxCellController(static_cast<ListBoxControl*>(m_pWindow.get()));
2637 OUString DbListBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/)
2639 OUString sText;
2640 if ( _rxField.is() )
2644 sText = _rxField->getString();
2645 if ( m_bBound )
2647 sal_Int32 nPos = ::comphelper::findValue( m_aValueList, sText );
2648 if ( nPos != -1 )
2649 sText = static_cast<svt::ListBoxControl*>(m_pWindow.get())->get_widget().get_text(nPos);
2650 else
2651 sText.clear();
2654 catch( const Exception& )
2656 DBG_UNHANDLED_EXCEPTION("svx");
2659 return sText;
2662 void DbListBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
2664 OUString sFormattedText( GetFormatText( _rxField, xFormatter ) );
2665 weld::ComboBox& rComboBox = static_cast<ListBoxControl*>(m_pWindow.get())->get_widget();
2666 if (!sFormattedText.isEmpty())
2667 rComboBox.set_active_text(sFormattedText);
2668 else
2669 rComboBox.set_active(-1);
2672 void DbListBox::updateFromModel( Reference< XPropertySet > _rxModel )
2674 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbListBox::updateFromModel: invalid call!" );
2676 Sequence< sal_Int16 > aSelection;
2677 _rxModel->getPropertyValue( FM_PROP_SELECT_SEQ ) >>= aSelection;
2679 sal_Int16 nSelection = -1;
2680 if ( aSelection.hasElements() )
2681 nSelection = aSelection[ 0 ];
2683 ListBoxControl* pControl = static_cast<ListBoxControl*>(m_pWindow.get());
2684 weld::ComboBox& rComboBox = pControl->get_widget();
2686 int nOldActive = rComboBox.get_active();
2687 if (nSelection >= 0 && nSelection < rComboBox.get_count())
2688 rComboBox.set_active(nSelection);
2689 else
2690 rComboBox.set_active(-1);
2692 if (nOldActive != rComboBox.get_active())
2693 pControl->TriggerAuxModify();
2696 bool DbListBox::commitControl()
2698 Any aVal;
2699 Sequence<sal_Int16> aSelectSeq;
2700 weld::ComboBox& rComboBox = static_cast<ListBoxControl*>(m_pWindow.get())->get_widget();
2701 auto nActive = rComboBox.get_active();
2702 if (nActive != -1)
2704 aSelectSeq.realloc(1);
2705 *aSelectSeq.getArray() = static_cast<sal_Int16>(nActive);
2707 aVal <<= aSelectSeq;
2708 m_rColumn.getModel()->setPropertyValue(FM_PROP_SELECT_SEQ, aVal);
2709 return true;
2712 DbFilterField::DbFilterField(const Reference< XComponentContext >& rxContext,DbGridColumn& _rColumn)
2713 :DbCellControl(_rColumn)
2714 ,OSQLParserClient(rxContext)
2715 ,m_nControlClass(css::form::FormComponentType::TEXTFIELD)
2716 ,m_bFilterList(false)
2717 ,m_bFilterListFilled(false)
2720 setAlignedController( false );
2723 DbFilterField::~DbFilterField()
2725 if (m_nControlClass == css::form::FormComponentType::CHECKBOX)
2726 static_cast<CheckBoxControl*>(m_pWindow.get())->SetClickHdl( Link<weld::Button&,void>() );
2730 void DbFilterField::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect)
2732 static const DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter | DrawTextFlags::Left;
2733 switch (m_nControlClass)
2735 case FormComponentType::CHECKBOX:
2737 // center the checkbox within the space available
2738 CheckBoxControl* pControl = static_cast<CheckBoxControl*>(m_pPainter.get());
2739 Size aBoxSize = pControl->GetBox().get_preferred_size();
2740 tools::Rectangle aRect(Point(rRect.Left() + ((rRect.GetWidth() - aBoxSize.Width()) / 2),
2741 rRect.Top() + ((rRect.GetHeight() - aBoxSize.Height()) / 2)),
2742 aBoxSize);
2744 DbCellControl::PaintCell(rDev, aRect);
2745 break;
2747 case FormComponentType::LISTBOX:
2748 rDev.DrawText(rRect, static_cast<ListBoxControl*>(m_pWindow.get())->get_widget().get_active_text(), nStyle);
2749 break;
2750 default:
2751 rDev.DrawText(rRect, m_aText, nStyle);
2755 void DbFilterField::SetList(const Any& rItems, bool bComboBox)
2757 css::uno::Sequence<OUString> aTest;
2758 rItems >>= aTest;
2759 if (!aTest.hasElements())
2760 return;
2762 if (bComboBox)
2764 ComboBoxControl* pField = static_cast<ComboBoxControl*>(m_pWindow.get());
2765 weld::ComboBox& rComboBox = pField->get_widget();
2766 for (const OUString& rString : std::as_const(aTest))
2767 rComboBox.append_text(rString);
2769 else
2771 ListBoxControl* pField = static_cast<ListBoxControl*>(m_pWindow.get());
2772 weld::ComboBox& rFieldBox = pField->get_widget();
2773 for (const OUString& rString : std::as_const(aTest))
2774 rFieldBox.append_text(rString);
2776 m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList;
2780 void DbFilterField::CreateControl(BrowserDataWin* pParent, const Reference< css::beans::XPropertySet >& xModel)
2782 switch (m_nControlClass)
2784 case css::form::FormComponentType::CHECKBOX:
2785 m_pWindow = VclPtr<CheckBoxControl>::Create(pParent);
2786 m_pWindow->SetPaintTransparent( true );
2787 static_cast<CheckBoxControl*>(m_pWindow.get())->SetClickHdl( LINK( this, DbFilterField, OnClick ) );
2789 m_pPainter = VclPtr<CheckBoxControl>::Create(pParent);
2790 m_pPainter->SetPaintTransparent( true );
2791 m_pPainter->SetBackground();
2792 break;
2793 case css::form::FormComponentType::LISTBOX:
2795 m_pWindow = VclPtr<ListBoxControl>::Create(pParent);
2796 Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST);
2797 SetList(aItems, false);
2798 } break;
2799 case css::form::FormComponentType::COMBOBOX:
2801 m_pWindow = VclPtr<ComboBoxControl>::Create(pParent);
2803 AllSettings aSettings = m_pWindow->GetSettings();
2804 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2805 aStyleSettings.SetSelectionOptions(
2806 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2807 aSettings.SetStyleSettings(aStyleSettings);
2808 m_pWindow->SetSettings(aSettings, true);
2810 if (!m_bFilterList)
2812 Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST);
2813 SetList(aItems, true);
2816 } break;
2817 default:
2819 m_pWindow = VclPtr<EditControl>::Create(pParent);
2820 AllSettings aSettings = m_pWindow->GetSettings();
2821 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2822 aStyleSettings.SetSelectionOptions(
2823 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2824 aSettings.SetStyleSettings(aStyleSettings);
2825 m_pWindow->SetSettings(aSettings, true);
2830 void DbFilterField::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor)
2832 Reference< css::beans::XPropertySet > xModel(m_rColumn.getModel());
2833 m_rColumn.SetAlignment(css::awt::TextAlign::LEFT);
2835 if (xModel.is())
2837 m_bFilterList = ::comphelper::hasProperty(FM_PROP_FILTERPROPOSAL, xModel) && ::comphelper::getBOOL(xModel->getPropertyValue(FM_PROP_FILTERPROPOSAL));
2838 if (m_bFilterList)
2839 m_nControlClass = css::form::FormComponentType::COMBOBOX;
2840 else
2842 sal_Int16 nClassId = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_CLASSID));
2843 switch (nClassId)
2845 case FormComponentType::CHECKBOX:
2846 case FormComponentType::LISTBOX:
2847 case FormComponentType::COMBOBOX:
2848 m_nControlClass = nClassId;
2849 break;
2850 default:
2851 if (m_bFilterList)
2852 m_nControlClass = FormComponentType::COMBOBOX;
2853 else
2854 m_nControlClass = FormComponentType::TEXTFIELD;
2859 CreateControl( &rParent, xModel );
2860 DbCellControl::Init( rParent, xCursor );
2862 // filter cells are never readonly
2863 if (m_pWindow)
2864 m_pWindow->SetEditableReadOnly(false);
2867 CellControllerRef DbFilterField::CreateController() const
2869 CellControllerRef xController;
2870 switch (m_nControlClass)
2872 case css::form::FormComponentType::CHECKBOX:
2873 xController = new CheckBoxCellController(static_cast<CheckBoxControl*>(m_pWindow.get()));
2874 break;
2875 case css::form::FormComponentType::LISTBOX:
2876 xController = new ListBoxCellController(static_cast<ListBoxControl*>(m_pWindow.get()));
2877 break;
2878 case css::form::FormComponentType::COMBOBOX:
2879 xController = new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2880 break;
2881 default:
2882 if (m_bFilterList)
2883 xController = new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2884 else
2885 xController = new EditCellController(static_cast<EditControlBase*>(m_pWindow.get()));
2887 return xController;
2890 void DbFilterField::updateFromModel( Reference< XPropertySet > _rxModel )
2892 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFilterField::updateFromModel: invalid call!" );
2894 OSL_FAIL( "DbFilterField::updateFromModel: not implemented yet (how the hell did you reach this?)!" );
2895 // TODO: implement this.
2896 // remember: updateFromModel should be some kind of opposite of commitControl
2899 bool DbFilterField::commitControl()
2901 OUString aText(m_aText);
2902 switch (m_nControlClass)
2904 case css::form::FormComponentType::CHECKBOX:
2905 return true;
2906 case css::form::FormComponentType::LISTBOX:
2908 aText.clear();
2909 weld::ComboBox& rComboBox = static_cast<svt::ListBoxControl*>(m_pWindow.get())->get_widget();
2910 auto nActive = rComboBox.get_active();
2911 if (nActive != -1)
2913 sal_Int16 nPos = static_cast<sal_Int16>(nActive);
2914 if ( ( nPos >= 0 ) && ( nPos < m_aValueList.getLength() ) )
2915 aText = m_aValueList.getConstArray()[nPos];
2918 if (m_aText != aText)
2920 m_aText = aText;
2921 m_aCommitLink.Call(*this);
2923 return true;
2925 case css::form::FormComponentType::COMBOBOX:
2927 aText = static_cast<ComboBoxControl*>(m_pWindow.get())->get_widget().get_active_text();
2928 break;
2930 default:
2932 aText = static_cast<EditControlBase*>(m_pWindow.get())->get_widget().get_text();
2933 break;
2937 if (m_aText != aText)
2939 // check the text with the SQL-Parser
2940 OUString aNewText(comphelper::string::stripEnd(aText, ' '));
2941 if (!aNewText.isEmpty())
2943 OUString aErrorMsg;
2944 Reference< XNumberFormatter > xNumberFormatter(m_rColumn.GetParent().getNumberFormatter());
2946 std::unique_ptr< OSQLParseNode > pParseNode = predicateTree(aErrorMsg, aNewText,xNumberFormatter, m_rColumn.GetField());
2947 if (pParseNode != nullptr)
2949 OUString aPreparedText;
2951 css::lang::Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
2953 Reference< XRowSet > xDataSourceRowSet(
2954 Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY);
2955 Reference< XConnection > xConnection(getConnection(xDataSourceRowSet));
2957 pParseNode->parseNodeToPredicateStr(aPreparedText,
2958 xConnection,
2959 xNumberFormatter,
2960 m_rColumn.GetField(),
2961 OUString(),
2962 aAppLocale,
2963 OUString("."),
2964 getParseContext());
2965 m_aText = aPreparedText;
2967 else
2970 SQLException aError;
2971 aError.Message = aErrorMsg;
2972 displayException(aError, m_pWindow->GetParent());
2973 // TODO: transport the title
2975 return false;
2978 else
2979 m_aText = aText;
2981 m_pWindow->SetText(m_aText);
2982 m_aCommitLink.Call(*this);
2984 return true;
2988 void DbFilterField::SetText(const OUString& rText)
2990 m_aText = rText;
2991 switch (m_nControlClass)
2993 case css::form::FormComponentType::CHECKBOX:
2995 TriState eState;
2996 if (rText == "1")
2997 eState = TRISTATE_TRUE;
2998 else if (rText == "0")
2999 eState = TRISTATE_FALSE;
3000 else
3001 eState = TRISTATE_INDET;
3003 static_cast<CheckBoxControl*>(m_pWindow.get())->SetState(eState);
3004 static_cast<CheckBoxControl*>(m_pPainter.get())->SetState(eState);
3005 } break;
3006 case css::form::FormComponentType::LISTBOX:
3008 sal_Int32 nPos = ::comphelper::findValue(m_aValueList, m_aText);
3009 static_cast<ListBoxControl*>(m_pWindow.get())->get_widget().set_active(nPos);
3010 } break;
3011 case css::form::FormComponentType::COMBOBOX:
3013 static_cast<ComboBoxControl*>(m_pWindow.get())->get_widget().set_entry_text(m_aText);
3014 break;
3016 default:
3018 static_cast<EditControlBase*>(m_pWindow.get())->get_widget().set_text(m_aText);
3019 break;
3023 // now force a repaint on the window
3024 m_rColumn.GetParent().RowModified(0);
3028 void DbFilterField::Update()
3030 // should we fill the combobox with a filter proposal?
3031 if (!m_bFilterList || m_bFilterListFilled)
3032 return;
3034 m_bFilterListFilled = true;
3035 Reference< css::beans::XPropertySet > xField = m_rColumn.GetField();
3036 if (!xField.is())
3037 return;
3039 OUString aName;
3040 xField->getPropertyValue(FM_PROP_NAME) >>= aName;
3042 // the columnmodel
3043 Reference< css::container::XChild > xModelAsChild(m_rColumn.getModel(), UNO_QUERY);
3044 // the grid model
3045 xModelAsChild.set(xModelAsChild->getParent(),UNO_QUERY);
3046 Reference< XRowSet > xForm(xModelAsChild->getParent(), UNO_QUERY);
3047 if (!xForm.is())
3048 return;
3050 Reference<XPropertySet> xFormProp(xForm,UNO_QUERY);
3051 Reference< XTablesSupplier > xSupTab;
3052 xFormProp->getPropertyValue("SingleSelectQueryComposer") >>= xSupTab;
3054 Reference< XConnection > xConnection(getConnection(xForm));
3055 if (!xSupTab.is())
3056 return;
3058 // search the field
3059 Reference< XColumnsSupplier > xSupCol(xSupTab,UNO_QUERY);
3060 Reference< css::container::XNameAccess > xFieldNames = xSupCol->getColumns();
3061 if (!xFieldNames->hasByName(aName))
3062 return;
3064 Reference< css::container::XNameAccess > xTablesNames = xSupTab->getTables();
3065 Reference< css::beans::XPropertySet > xComposerFieldAsSet(xFieldNames->getByName(aName),UNO_QUERY);
3067 if (!xComposerFieldAsSet.is() ||
3068 !::comphelper::hasProperty(FM_PROP_TABLENAME, xComposerFieldAsSet) ||
3069 !::comphelper::hasProperty(FM_PROP_FIELDSOURCE, xComposerFieldAsSet))
3070 return;
3072 OUString aFieldName;
3073 OUString aTableName;
3074 xComposerFieldAsSet->getPropertyValue(FM_PROP_FIELDSOURCE) >>= aFieldName;
3075 xComposerFieldAsSet->getPropertyValue(FM_PROP_TABLENAME) >>= aTableName;
3077 // no possibility to create a select statement
3078 // looking for the complete table name
3079 if (!xTablesNames->hasByName(aTableName))
3080 return;
3082 // build a statement and send as query;
3083 // Access to the connection
3084 Reference< XStatement > xStatement;
3085 Reference< XResultSet > xListCursor;
3086 Reference< css::sdb::XColumn > xDataField;
3090 Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData();
3092 OUString aQuote(xMeta->getIdentifierQuoteString());
3093 OUStringBuffer aStatement("SELECT DISTINCT ");
3094 aStatement.append(quoteName(aQuote, aName));
3095 if (!aFieldName.isEmpty() && aName != aFieldName)
3097 aStatement.append(" AS ");
3098 aStatement.append(quoteName(aQuote, aFieldName));
3101 aStatement.append(" FROM ");
3103 Reference< XPropertySet > xTableNameAccess(xTablesNames->getByName(aTableName), UNO_QUERY_THROW);
3104 aStatement.append(composeTableNameForSelect(xConnection, xTableNameAccess));
3106 xStatement = xConnection->createStatement();
3107 Reference< css::beans::XPropertySet > xStatementProps(xStatement, UNO_QUERY);
3108 xStatementProps->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, makeAny(true));
3110 xListCursor = xStatement->executeQuery(aStatement.makeStringAndClear());
3112 Reference< css::sdbcx::XColumnsSupplier > xSupplyCols(xListCursor, UNO_QUERY);
3113 Reference< css::container::XIndexAccess > xFields(xSupplyCols->getColumns(), UNO_QUERY);
3114 xDataField.set(xFields->getByIndex(0), css::uno::UNO_QUERY);
3115 if (!xDataField.is())
3116 return;
3118 catch(const Exception&)
3120 ::comphelper::disposeComponent(xStatement);
3121 return;
3124 sal_Int16 i = 0;
3125 ::std::vector< OUString > aStringList;
3126 aStringList.reserve(16);
3127 OUString aStr;
3128 css::util::Date aNullDate = m_rColumn.GetParent().getNullDate();
3129 sal_Int32 nFormatKey = m_rColumn.GetKey();
3130 Reference< XNumberFormatter > xFormatter = m_rColumn.GetParent().getNumberFormatter();
3131 sal_Int16 nKeyType = ::comphelper::getNumberFormatType(xFormatter->getNumberFormatsSupplier()->getNumberFormats(), nFormatKey);
3133 while (!xListCursor->isAfterLast() && i++ < SHRT_MAX) // max number of entries
3135 aStr = getFormattedValue(xDataField, xFormatter, aNullDate, nFormatKey, nKeyType);
3136 aStringList.push_back(aStr);
3137 (void)xListCursor->next();
3140 ComboBoxControl* pField = static_cast<ComboBoxControl*>(m_pWindow.get());
3141 weld::ComboBox& rComboBox = pField->get_widget();
3142 // filling the entries for the combobox
3143 for (const auto& rString : aStringList)
3144 rComboBox.append_text(rString);
3147 OUString DbFilterField::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/)
3149 return OUString();
3152 void DbFilterField::UpdateFromField(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/)
3154 OSL_FAIL( "DbFilterField::UpdateFromField: cannot update a filter control from a field!" );
3157 IMPL_LINK_NOARG(DbFilterField, OnClick, weld::Button&, void)
3159 TriState eState = static_cast<CheckBoxControl*>(m_pWindow.get())->GetState();
3160 OUStringBuffer aTextBuf;
3162 Reference< XRowSet > xDataSourceRowSet(
3163 Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY);
3164 Reference< XConnection > xConnection(getConnection(xDataSourceRowSet));
3165 const sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( xConnection ).getBooleanComparisonMode();
3167 switch (eState)
3169 case TRISTATE_TRUE:
3170 ::dbtools::getBooleanComparisonPredicate("", true, nBooleanComparisonMode, aTextBuf);
3171 break;
3172 case TRISTATE_FALSE:
3173 ::dbtools::getBooleanComparisonPredicate("", false, nBooleanComparisonMode, aTextBuf);
3174 break;
3175 case TRISTATE_INDET:
3176 break;
3179 const OUString aText(aTextBuf.makeStringAndClear());
3181 if (m_aText != aText)
3183 m_aText = aText;
3184 m_aCommitLink.Call(*this);
3188 FmXGridCell::FmXGridCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> _pControl )
3189 :OComponentHelper(m_aMutex)
3190 ,m_pColumn(pColumn)
3191 ,m_pCellControl( std::move(_pControl) )
3192 ,m_aWindowListeners( m_aMutex )
3193 ,m_aFocusListeners( m_aMutex )
3194 ,m_aKeyListeners( m_aMutex )
3195 ,m_aMouseListeners( m_aMutex )
3196 ,m_aMouseMotionListeners( m_aMutex )
3200 void FmXGridCell::init()
3202 svt::ControlBase* pEventWindow( getEventWindow() );
3203 if ( pEventWindow )
3205 pEventWindow->AddEventListener( LINK( this, FmXGridCell, OnWindowEvent ) );
3206 pEventWindow->SetFocusInHdl(LINK( this, FmXGridCell, OnFocusGained));
3207 pEventWindow->SetFocusOutHdl(LINK( this, FmXGridCell, OnFocusLost));
3208 pEventWindow->SetMousePressHdl(LINK( this, FmXGridCell, OnMousePress));
3209 pEventWindow->SetMouseReleaseHdl(LINK( this, FmXGridCell, OnMouseRelease));
3210 pEventWindow->SetMouseMoveHdl(LINK( this, FmXGridCell, OnMouseMove));
3214 svt::ControlBase* FmXGridCell::getEventWindow() const
3216 if ( m_pCellControl )
3217 return &m_pCellControl->GetWindow();
3218 return nullptr;
3221 FmXGridCell::~FmXGridCell()
3223 if (!OComponentHelper::rBHelper.bDisposed)
3225 acquire();
3226 dispose();
3231 void FmXGridCell::SetTextLineColor()
3233 if (m_pCellControl)
3234 m_pCellControl->SetTextLineColor();
3237 void FmXGridCell::SetTextLineColor(const Color& _rColor)
3239 if (m_pCellControl)
3240 m_pCellControl->SetTextLineColor(_rColor);
3243 // XTypeProvider
3245 Sequence< Type > SAL_CALL FmXGridCell::getTypes( )
3247 Sequence< uno::Type > aTypes = ::comphelper::concatSequences(
3248 ::cppu::OComponentHelper::getTypes(),
3249 FmXGridCell_Base::getTypes()
3251 if ( m_pCellControl )
3252 aTypes = ::comphelper::concatSequences(
3253 aTypes,
3254 FmXGridCell_WindowBase::getTypes()
3256 return aTypes;
3260 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXGridCell )
3262 // OComponentHelper
3264 void FmXGridCell::disposing()
3266 lang::EventObject aEvent( *this );
3267 m_aWindowListeners.disposeAndClear( aEvent );
3268 m_aFocusListeners.disposeAndClear( aEvent );
3269 m_aKeyListeners.disposeAndClear( aEvent );
3270 m_aMouseListeners.disposeAndClear( aEvent );
3271 m_aMouseMotionListeners.disposeAndClear( aEvent );
3273 OComponentHelper::disposing();
3274 m_pColumn = nullptr;
3275 m_pCellControl.reset();
3279 Any SAL_CALL FmXGridCell::queryAggregation( const css::uno::Type& _rType )
3281 Any aReturn = OComponentHelper::queryAggregation( _rType );
3283 if ( !aReturn.hasValue() )
3284 aReturn = FmXGridCell_Base::queryInterface( _rType );
3286 if ( !aReturn.hasValue() && ( m_pCellControl != nullptr ) )
3287 aReturn = FmXGridCell_WindowBase::queryInterface( _rType );
3289 return aReturn;
3292 // css::awt::XControl
3294 Reference< XInterface > FmXGridCell::getContext()
3296 return Reference< XInterface > ();
3300 Reference< css::awt::XControlModel > FmXGridCell::getModel()
3302 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3303 return Reference< css::awt::XControlModel > (m_pColumn->getModel(), UNO_QUERY);
3306 // css::form::XBoundControl
3308 sal_Bool FmXGridCell::getLock()
3310 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3311 return m_pColumn->isLocked();
3315 void FmXGridCell::setLock(sal_Bool _bLock)
3317 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3318 if (getLock() == _bLock)
3319 return;
3320 else
3322 ::osl::MutexGuard aGuard(m_aMutex);
3323 m_pColumn->setLock(_bLock);
3328 void SAL_CALL FmXGridCell::setPosSize( ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int16 )
3330 OSL_FAIL( "FmXGridCell::setPosSize: not implemented" );
3331 // not allowed to tamper with this for a grid cell
3335 awt::Rectangle SAL_CALL FmXGridCell::getPosSize( )
3337 OSL_FAIL( "FmXGridCell::getPosSize: not implemented" );
3338 return awt::Rectangle();
3342 void SAL_CALL FmXGridCell::setVisible( sal_Bool )
3344 OSL_FAIL( "FmXGridCell::setVisible: not implemented" );
3345 // not allowed to tamper with this for a grid cell
3349 void SAL_CALL FmXGridCell::setEnable( sal_Bool )
3351 OSL_FAIL( "FmXGridCell::setEnable: not implemented" );
3352 // not allowed to tamper with this for a grid cell
3356 void SAL_CALL FmXGridCell::setFocus( )
3358 OSL_FAIL( "FmXGridCell::setFocus: not implemented" );
3359 // not allowed to tamper with this for a grid cell
3363 void SAL_CALL FmXGridCell::addWindowListener( const Reference< awt::XWindowListener >& _rxListener )
3365 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3366 m_aWindowListeners.addInterface( _rxListener );
3370 void SAL_CALL FmXGridCell::removeWindowListener( const Reference< awt::XWindowListener >& _rxListener )
3372 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3373 m_aWindowListeners.removeInterface( _rxListener );
3377 void SAL_CALL FmXGridCell::addFocusListener( const Reference< awt::XFocusListener >& _rxListener )
3379 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3380 m_aFocusListeners.addInterface( _rxListener );
3384 void SAL_CALL FmXGridCell::removeFocusListener( const Reference< awt::XFocusListener >& _rxListener )
3386 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3387 m_aFocusListeners.removeInterface( _rxListener );
3391 void SAL_CALL FmXGridCell::addKeyListener( const Reference< awt::XKeyListener >& _rxListener )
3393 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3394 m_aKeyListeners.addInterface( _rxListener );
3398 void SAL_CALL FmXGridCell::removeKeyListener( const Reference< awt::XKeyListener >& _rxListener )
3400 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3401 m_aKeyListeners.removeInterface( _rxListener );
3405 void SAL_CALL FmXGridCell::addMouseListener( const Reference< awt::XMouseListener >& _rxListener )
3407 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3408 m_aMouseListeners.addInterface( _rxListener );
3412 void SAL_CALL FmXGridCell::removeMouseListener( const Reference< awt::XMouseListener >& _rxListener )
3414 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3415 m_aMouseListeners.removeInterface( _rxListener );
3419 void SAL_CALL FmXGridCell::addMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener )
3421 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3422 m_aMouseMotionListeners.addInterface( _rxListener );
3426 void SAL_CALL FmXGridCell::removeMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener )
3428 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3429 m_aMouseMotionListeners.removeInterface( _rxListener );
3432 void SAL_CALL FmXGridCell::addPaintListener( const Reference< awt::XPaintListener >& )
3434 OSL_FAIL( "FmXGridCell::addPaintListener: not implemented" );
3437 void SAL_CALL FmXGridCell::removePaintListener( const Reference< awt::XPaintListener >& )
3439 OSL_FAIL( "FmXGridCell::removePaintListener: not implemented" );
3442 IMPL_LINK( FmXGridCell, OnWindowEvent, VclWindowEvent&, _rEvent, void )
3444 ENSURE_OR_THROW( _rEvent.GetWindow(), "illegal window" );
3445 onWindowEvent(_rEvent.GetId(), _rEvent.GetData());
3448 void FmXGridCell::onFocusGained( const awt::FocusEvent& _rEvent )
3450 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3451 m_aFocusListeners.notifyEach( &awt::XFocusListener::focusGained, _rEvent );
3454 void FmXGridCell::onFocusLost( const awt::FocusEvent& _rEvent )
3456 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3457 m_aFocusListeners.notifyEach( &awt::XFocusListener::focusLost, _rEvent );
3460 IMPL_LINK_NOARG(FmXGridCell, OnFocusGained, LinkParamNone*, void)
3462 if (!m_aFocusListeners.getLength())
3463 return;
3465 awt::FocusEvent aEvent;
3466 aEvent.Source = *this;
3467 aEvent.Temporary = false;
3469 onFocusGained(aEvent);
3472 IMPL_LINK_NOARG(FmXGridCell, OnFocusLost, LinkParamNone*, void)
3474 if (!m_aFocusListeners.getLength())
3475 return;
3477 awt::FocusEvent aEvent;
3478 aEvent.Source = *this;
3479 aEvent.Temporary = false;
3481 onFocusLost(aEvent);
3484 IMPL_LINK(FmXGridCell, OnMousePress, const MouseEvent&, rEventData, void)
3486 if (!m_aMouseListeners.getLength())
3487 return;
3489 awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(rEventData, *this));
3490 m_aMouseListeners.notifyEach(&awt::XMouseListener::mousePressed, aEvent);
3493 IMPL_LINK(FmXGridCell, OnMouseRelease, const MouseEvent&, rEventData, void)
3495 if (!m_aMouseListeners.getLength())
3496 return;
3498 awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(rEventData, *this));
3499 m_aMouseListeners.notifyEach(&awt::XMouseListener::mouseReleased, aEvent);
3502 IMPL_LINK(FmXGridCell, OnMouseMove, const MouseEvent&, rMouseEvent, void)
3504 if ( rMouseEvent.IsEnterWindow() || rMouseEvent.IsLeaveWindow() )
3506 if ( m_aMouseListeners.getLength() != 0 )
3508 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) );
3509 m_aMouseListeners.notifyEach( rMouseEvent.IsEnterWindow() ? &awt::XMouseListener::mouseEntered: &awt::XMouseListener::mouseExited, aEvent );
3512 else if ( !rMouseEvent.IsEnterWindow() && !rMouseEvent.IsLeaveWindow() )
3514 if ( m_aMouseMotionListeners.getLength() != 0 )
3516 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) );
3517 aEvent.ClickCount = 0;
3518 const bool bSimpleMove = bool( rMouseEvent.GetMode() & MouseEventModifiers::SIMPLEMOVE );
3519 m_aMouseMotionListeners.notifyEach( bSimpleMove ? &awt::XMouseMotionListener::mouseMoved: &awt::XMouseMotionListener::mouseDragged, aEvent );
3524 void FmXGridCell::onWindowEvent(const VclEventId _nEventId, const void* _pEventData)
3526 switch ( _nEventId )
3528 case VclEventId::WindowKeyInput:
3529 case VclEventId::WindowKeyUp:
3531 if ( !m_aKeyListeners.getLength() )
3532 break;
3534 const bool bKeyPressed = ( _nEventId == VclEventId::WindowKeyInput );
3535 awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent( *static_cast< const ::KeyEvent* >( _pEventData ), *this ) );
3536 m_aKeyListeners.notifyEach( bKeyPressed ? &awt::XKeyListener::keyPressed: &awt::XKeyListener::keyReleased, aEvent );
3538 break;
3539 default: break;
3544 void FmXDataCell::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect,
3545 const Reference< css::sdb::XColumn >& _rxField,
3546 const Reference< XNumberFormatter >& xFormatter)
3548 m_pCellControl->PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
3552 void FmXDataCell::UpdateFromColumn()
3554 Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue());
3555 if (xField.is())
3556 m_pCellControl->UpdateFromField(xField, m_pColumn->GetParent().getNumberFormatter());
3560 FmXTextCell::FmXTextCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
3561 :FmXDataCell( pColumn, std::move(pControl) )
3562 ,m_bFastPaint( true )
3567 void FmXTextCell::PaintFieldToCell(OutputDevice& rDev,
3568 const tools::Rectangle& rRect,
3569 const Reference< css::sdb::XColumn >& _rxField,
3570 const Reference< XNumberFormatter >& xFormatter)
3572 if ( !m_bFastPaint )
3574 FmXDataCell::PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
3575 return;
3578 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter;
3579 if ( ( rDev.GetOutDevType() == OUTDEV_WINDOW ) && !static_cast< vcl::Window& >( rDev ).IsEnabled() )
3580 nStyle |= DrawTextFlags::Disable;
3582 switch (m_pColumn->GetAlignment())
3584 case css::awt::TextAlign::RIGHT:
3585 nStyle |= DrawTextFlags::Right;
3586 break;
3587 case css::awt::TextAlign::CENTER:
3588 nStyle |= DrawTextFlags::Center;
3589 break;
3590 default:
3591 nStyle |= DrawTextFlags::Left;
3596 const Color* pColor = nullptr;
3597 OUString aText = GetText(_rxField, xFormatter, &pColor);
3598 if (pColor != nullptr)
3600 Color aOldTextColor( rDev.GetTextColor() );
3601 rDev.SetTextColor( *pColor );
3602 rDev.DrawText(rRect, aText, nStyle);
3603 rDev.SetTextColor( aOldTextColor );
3605 else
3606 rDev.DrawText(rRect, aText, nStyle);
3608 catch (const Exception&)
3610 TOOLS_WARN_EXCEPTION("svx.fmcomp", "PaintFieldToCell");
3614 FmXEditCell::FmXEditCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
3615 :FmXTextCell( pColumn, std::move(pControl) )
3616 ,m_aTextListeners(m_aMutex)
3617 ,m_aChangeListeners( m_aMutex )
3618 ,m_pEditImplementation( nullptr )
3619 ,m_bOwnEditImplementation( false )
3622 DbTextField* pTextField = dynamic_cast<DbTextField*>( m_pCellControl.get() );
3623 if ( pTextField )
3626 m_pEditImplementation = pTextField->GetEditImplementation();
3627 if ( !pTextField->IsSimpleEdit() )
3628 m_bFastPaint = false;
3630 else
3632 m_pEditImplementation = new EntryImplementation(static_cast<EditControlBase&>(m_pCellControl->GetWindow()));
3633 m_bOwnEditImplementation = true;
3635 m_pEditImplementation->SetAuxModifyHdl(LINK(this, FmXEditCell, ModifyHdl));
3638 FmXEditCell::~FmXEditCell()
3640 if (!OComponentHelper::rBHelper.bDisposed)
3642 acquire();
3643 dispose();
3647 // OComponentHelper
3648 void FmXEditCell::disposing()
3650 css::lang::EventObject aEvt(*this);
3651 m_aTextListeners.disposeAndClear(aEvt);
3652 m_aChangeListeners.disposeAndClear(aEvt);
3654 if ( m_bOwnEditImplementation )
3655 delete m_pEditImplementation;
3656 m_pEditImplementation = nullptr;
3658 FmXDataCell::disposing();
3661 Any SAL_CALL FmXEditCell::queryAggregation( const css::uno::Type& _rType )
3663 Any aReturn = FmXTextCell::queryAggregation( _rType );
3665 if ( !aReturn.hasValue() )
3666 aReturn = FmXEditCell_Base::queryInterface( _rType );
3668 return aReturn;
3671 Sequence< css::uno::Type > SAL_CALL FmXEditCell::getTypes( )
3673 return ::comphelper::concatSequences(
3674 FmXTextCell::getTypes(),
3675 FmXEditCell_Base::getTypes()
3679 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXEditCell )
3681 // css::awt::XTextComponent
3682 void SAL_CALL FmXEditCell::addTextListener(const Reference< css::awt::XTextListener >& l)
3684 m_aTextListeners.addInterface( l );
3688 void SAL_CALL FmXEditCell::removeTextListener(const Reference< css::awt::XTextListener >& l)
3690 m_aTextListeners.removeInterface( l );
3693 void SAL_CALL FmXEditCell::setText( const OUString& aText )
3695 ::osl::MutexGuard aGuard( m_aMutex );
3697 if ( m_pEditImplementation )
3699 m_pEditImplementation->SetText( aText );
3701 // In Java, a textChanged is fired as well; not in VCL.
3702 // css::awt::Toolkit must be Java-compliant...
3703 onTextChanged();
3707 void SAL_CALL FmXEditCell::insertText(const css::awt::Selection& rSel, const OUString& aText)
3709 ::osl::MutexGuard aGuard( m_aMutex );
3711 if ( m_pEditImplementation )
3713 m_pEditImplementation->SetSelection( Selection( rSel.Min, rSel.Max ) );
3714 m_pEditImplementation->ReplaceSelected( aText );
3718 OUString SAL_CALL FmXEditCell::getText()
3720 ::osl::MutexGuard aGuard( m_aMutex );
3722 OUString aText;
3723 if ( m_pEditImplementation )
3725 if ( m_pEditImplementation->GetControl().IsVisible() && m_pColumn->GetParent().getDisplaySynchron())
3727 // if the display isn't sync with the cursor we can't ask the edit field
3728 LineEnd eLineEndFormat = getModelLineEndSetting( m_pColumn->getModel() );
3729 aText = m_pEditImplementation->GetText( eLineEndFormat );
3731 else
3733 Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue());
3734 if (xField.is())
3735 aText = GetText(xField, m_pColumn->GetParent().getNumberFormatter());
3738 return aText;
3741 OUString SAL_CALL FmXEditCell::getSelectedText()
3743 ::osl::MutexGuard aGuard( m_aMutex );
3745 OUString aText;
3746 if ( m_pEditImplementation )
3748 LineEnd eLineEndFormat = m_pColumn ? getModelLineEndSetting( m_pColumn->getModel() ) : LINEEND_LF;
3749 aText = m_pEditImplementation->GetSelected( eLineEndFormat );
3751 return aText;
3754 void SAL_CALL FmXEditCell::setSelection( const css::awt::Selection& aSelection )
3756 ::osl::MutexGuard aGuard( m_aMutex );
3758 if ( m_pEditImplementation )
3759 m_pEditImplementation->SetSelection( Selection( aSelection.Min, aSelection.Max ) );
3762 css::awt::Selection SAL_CALL FmXEditCell::getSelection()
3764 ::osl::MutexGuard aGuard( m_aMutex );
3766 Selection aSel;
3767 if ( m_pEditImplementation )
3768 aSel = m_pEditImplementation->GetSelection();
3770 return css::awt::Selection(aSel.Min(), aSel.Max());
3773 sal_Bool SAL_CALL FmXEditCell::isEditable()
3775 ::osl::MutexGuard aGuard( m_aMutex );
3777 return m_pEditImplementation && !m_pEditImplementation->IsReadOnly() && m_pEditImplementation->GetControl().IsEnabled();
3780 void SAL_CALL FmXEditCell::setEditable( sal_Bool bEditable )
3782 ::osl::MutexGuard aGuard( m_aMutex );
3784 if ( m_pEditImplementation )
3785 m_pEditImplementation->SetReadOnly( !bEditable );
3788 sal_Int16 SAL_CALL FmXEditCell::getMaxTextLen()
3790 ::osl::MutexGuard aGuard( m_aMutex );
3792 return m_pEditImplementation ? m_pEditImplementation->GetMaxTextLen() : 0;
3795 void SAL_CALL FmXEditCell::setMaxTextLen( sal_Int16 nLen )
3797 ::osl::MutexGuard aGuard( m_aMutex );
3799 if ( m_pEditImplementation )
3800 m_pEditImplementation->SetMaxTextLen( nLen );
3803 void SAL_CALL FmXEditCell::addChangeListener( const Reference< form::XChangeListener >& Listener )
3805 m_aChangeListeners.addInterface( Listener );
3808 void SAL_CALL FmXEditCell::removeChangeListener( const Reference< form::XChangeListener >& Listener )
3810 m_aChangeListeners.removeInterface( Listener );
3813 void FmXEditCell::onTextChanged()
3815 css::awt::TextEvent aEvent;
3816 aEvent.Source = *this;
3817 m_aTextListeners.notifyEach( &awt::XTextListener::textChanged, aEvent );
3820 void FmXEditCell::onFocusGained( const awt::FocusEvent& _rEvent )
3822 FmXTextCell::onFocusGained( _rEvent );
3823 m_sValueOnEnter = getText();
3826 void FmXEditCell::onFocusLost( const awt::FocusEvent& _rEvent )
3828 FmXTextCell::onFocusLost( _rEvent );
3830 if ( getText() != m_sValueOnEnter )
3832 lang::EventObject aEvent( *this );
3833 m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvent );
3837 IMPL_LINK_NOARG(FmXEditCell, ModifyHdl, LinkParamNone*, void)
3839 if (m_aTextListeners.getLength())
3840 onTextChanged();
3843 FmXCheckBoxCell::FmXCheckBoxCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
3844 :FmXDataCell( pColumn, std::move(pControl) )
3845 ,m_aItemListeners(m_aMutex)
3846 ,m_aActionListeners( m_aMutex )
3847 ,m_pBox( & static_cast< CheckBoxControl& >( m_pCellControl->GetWindow() ) )
3849 m_pBox->SetAuxModifyHdl(LINK(this, FmXCheckBoxCell, ModifyHdl));
3852 FmXCheckBoxCell::~FmXCheckBoxCell()
3854 if (!OComponentHelper::rBHelper.bDisposed)
3856 acquire();
3857 dispose();
3861 // OComponentHelper
3862 void FmXCheckBoxCell::disposing()
3864 css::lang::EventObject aEvt(*this);
3865 m_aItemListeners.disposeAndClear(aEvt);
3866 m_aActionListeners.disposeAndClear(aEvt);
3868 m_pBox->SetClickHdl(Link<weld::Button&,void>());
3869 m_pBox = nullptr;
3871 FmXDataCell::disposing();
3875 Any SAL_CALL FmXCheckBoxCell::queryAggregation( const css::uno::Type& _rType )
3877 Any aReturn = FmXDataCell::queryAggregation( _rType );
3879 if ( !aReturn.hasValue() )
3880 aReturn = FmXCheckBoxCell_Base::queryInterface( _rType );
3882 return aReturn;
3886 Sequence< css::uno::Type > SAL_CALL FmXCheckBoxCell::getTypes( )
3888 return ::comphelper::concatSequences(
3889 FmXDataCell::getTypes(),
3890 FmXCheckBoxCell_Base::getTypes()
3895 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXCheckBoxCell )
3897 void SAL_CALL FmXCheckBoxCell::addItemListener( const Reference< css::awt::XItemListener >& l )
3899 m_aItemListeners.addInterface( l );
3902 void SAL_CALL FmXCheckBoxCell::removeItemListener( const Reference< css::awt::XItemListener >& l )
3904 m_aItemListeners.removeInterface( l );
3907 void SAL_CALL FmXCheckBoxCell::setState( sal_Int16 n )
3909 ::osl::MutexGuard aGuard( m_aMutex );
3911 if (m_pBox)
3913 UpdateFromColumn();
3914 m_pBox->SetState( static_cast<TriState>(n) );
3918 sal_Int16 SAL_CALL FmXCheckBoxCell::getState()
3920 ::osl::MutexGuard aGuard( m_aMutex );
3922 if (m_pBox)
3924 UpdateFromColumn();
3925 return static_cast<sal_Int16>(m_pBox->GetState());
3927 return TRISTATE_INDET;
3930 void SAL_CALL FmXCheckBoxCell::enableTriState(sal_Bool b)
3932 ::osl::MutexGuard aGuard( m_aMutex );
3934 if (m_pBox)
3935 m_pBox->EnableTriState( b );
3938 void SAL_CALL FmXCheckBoxCell::addActionListener( const Reference< awt::XActionListener >& Listener )
3940 m_aActionListeners.addInterface( Listener );
3944 void SAL_CALL FmXCheckBoxCell::removeActionListener( const Reference< awt::XActionListener >& Listener )
3946 m_aActionListeners.removeInterface( Listener );
3949 void SAL_CALL FmXCheckBoxCell::setLabel( const OUString& Label )
3951 SolarMutexGuard aGuard;
3952 if ( m_pColumn )
3954 DbGridControl& rGrid( m_pColumn->GetParent() );
3955 rGrid.SetColumnTitle( rGrid.GetColumnId( m_pColumn->GetFieldPos() ), Label );
3959 void SAL_CALL FmXCheckBoxCell::setActionCommand( const OUString& Command )
3961 m_aActionCommand = Command;
3964 IMPL_LINK_NOARG(FmXCheckBoxCell, ModifyHdl, LinkParamNone*, void)
3966 // check boxes are to be committed immediately (this holds for ordinary check box controls in
3967 // documents, and this must hold for check boxes in grid columns, too
3968 // 91210 - 22.08.2001 - frank.schoenheit@sun.com
3969 m_pCellControl->Commit();
3971 Reference< XWindow > xKeepAlive( this );
3972 if ( m_aItemListeners.getLength() && m_pBox )
3974 awt::ItemEvent aEvent;
3975 aEvent.Source = *this;
3976 aEvent.Highlighted = 0;
3977 aEvent.Selected = m_pBox->GetState();
3978 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
3980 if ( m_aActionListeners.getLength() )
3982 awt::ActionEvent aEvent;
3983 aEvent.Source = *this;
3984 aEvent.ActionCommand = m_aActionCommand;
3985 m_aActionListeners.notifyEach( &awt::XActionListener::actionPerformed, aEvent );
3989 FmXListBoxCell::FmXListBoxCell(DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl)
3990 : FmXTextCell(pColumn, std::move(pControl))
3991 , m_aItemListeners(m_aMutex)
3992 , m_aActionListeners(m_aMutex)
3993 , m_pBox(&static_cast<svt::ListBoxControl&>(m_pCellControl->GetWindow()))
3994 , m_nLines(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount())
3995 , m_bMulti(false)
3997 m_pBox->SetAuxModifyHdl(LINK(this, FmXListBoxCell, ChangedHdl));
4000 FmXListBoxCell::~FmXListBoxCell()
4002 if (!OComponentHelper::rBHelper.bDisposed)
4004 acquire();
4005 dispose();
4009 // OComponentHelper
4010 void FmXListBoxCell::disposing()
4012 css::lang::EventObject aEvt(*this);
4013 m_aItemListeners.disposeAndClear(aEvt);
4014 m_aActionListeners.disposeAndClear(aEvt);
4016 m_pBox->SetAuxModifyHdl(Link<bool,void>());
4017 m_pBox = nullptr;
4019 FmXTextCell::disposing();
4022 Any SAL_CALL FmXListBoxCell::queryAggregation( const css::uno::Type& _rType )
4024 Any aReturn = FmXTextCell::queryAggregation(_rType);
4026 if ( !aReturn.hasValue() )
4027 aReturn = FmXListBoxCell_Base::queryInterface( _rType );
4029 return aReturn;
4032 Sequence< css::uno::Type > SAL_CALL FmXListBoxCell::getTypes( )
4034 return ::comphelper::concatSequences(
4035 FmXTextCell::getTypes(),
4036 FmXListBoxCell_Base::getTypes()
4040 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXListBoxCell )
4042 void SAL_CALL FmXListBoxCell::addItemListener(const Reference< css::awt::XItemListener >& l)
4044 m_aItemListeners.addInterface( l );
4047 void SAL_CALL FmXListBoxCell::removeItemListener(const Reference< css::awt::XItemListener >& l)
4049 m_aItemListeners.removeInterface( l );
4052 void SAL_CALL FmXListBoxCell::addActionListener(const Reference< css::awt::XActionListener >& l)
4054 m_aActionListeners.addInterface( l );
4057 void SAL_CALL FmXListBoxCell::removeActionListener(const Reference< css::awt::XActionListener >& l)
4059 m_aActionListeners.removeInterface( l );
4062 void SAL_CALL FmXListBoxCell::addItem(const OUString& aItem, sal_Int16 nPos)
4064 ::osl::MutexGuard aGuard( m_aMutex );
4065 if (m_pBox)
4067 weld::ComboBox& rBox = m_pBox->get_widget();
4068 rBox.insert_text(nPos, aItem);
4072 void SAL_CALL FmXListBoxCell::addItems(const css::uno::Sequence<OUString>& aItems, sal_Int16 nPos)
4074 ::osl::MutexGuard aGuard( m_aMutex );
4075 if (m_pBox)
4077 weld::ComboBox& rBox = m_pBox->get_widget();
4078 sal_uInt16 nP = nPos;
4079 for ( const auto& rItem : aItems )
4081 rBox.insert_text(nP, rItem);
4082 if ( nPos != -1 ) // Not if 0xFFFF, because LIST_APPEND
4083 nP++;
4088 void SAL_CALL FmXListBoxCell::removeItems(sal_Int16 nPos, sal_Int16 nCount)
4090 ::osl::MutexGuard aGuard( m_aMutex );
4091 if ( m_pBox )
4093 weld::ComboBox& rBox = m_pBox->get_widget();
4094 for ( sal_uInt16 n = nCount; n; )
4095 rBox.remove( nPos + (--n) );
4099 sal_Int16 SAL_CALL FmXListBoxCell::getItemCount()
4101 ::osl::MutexGuard aGuard( m_aMutex );
4102 if (!m_pBox)
4103 return 0;
4104 weld::ComboBox& rBox = m_pBox->get_widget();
4105 return rBox.get_count();
4108 OUString SAL_CALL FmXListBoxCell::getItem(sal_Int16 nPos)
4110 ::osl::MutexGuard aGuard( m_aMutex );
4111 if (!m_pBox)
4112 return OUString();
4113 weld::ComboBox& rBox = m_pBox->get_widget();
4114 return rBox.get_text(nPos);
4117 css::uno::Sequence<OUString> SAL_CALL FmXListBoxCell::getItems()
4119 ::osl::MutexGuard aGuard( m_aMutex );
4121 css::uno::Sequence<OUString> aSeq;
4122 if (m_pBox)
4124 weld::ComboBox& rBox = m_pBox->get_widget();
4125 const sal_Int32 nEntries = rBox.get_count();
4126 aSeq = css::uno::Sequence<OUString>( nEntries );
4127 for ( sal_Int32 n = nEntries; n; )
4129 --n;
4130 aSeq.getArray()[n] = rBox.get_text( n );
4133 return aSeq;
4136 sal_Int16 SAL_CALL FmXListBoxCell::getSelectedItemPos()
4138 ::osl::MutexGuard aGuard( m_aMutex );
4139 if (m_pBox)
4141 UpdateFromColumn();
4142 weld::ComboBox& rBox = m_pBox->get_widget();
4143 sal_Int32 nPos = rBox.get_active();
4144 if (nPos > SHRT_MAX || nPos < SHRT_MIN)
4145 throw std::out_of_range("awt::XListBox::getSelectedItemPos can only return a short");
4146 return nPos;
4148 return 0;
4151 Sequence< sal_Int16 > SAL_CALL FmXListBoxCell::getSelectedItemsPos()
4153 ::osl::MutexGuard aGuard( m_aMutex );
4154 Sequence<sal_Int16> aSeq;
4156 if (m_pBox)
4158 UpdateFromColumn();
4159 weld::ComboBox& rBox = m_pBox->get_widget();
4160 auto nActive = rBox.get_active();
4161 if (nActive != -1)
4163 aSeq = Sequence<sal_Int16>(1);
4164 aSeq.getArray()[0] = nActive;
4167 return aSeq;
4170 OUString SAL_CALL FmXListBoxCell::getSelectedItem()
4172 ::osl::MutexGuard aGuard( m_aMutex );
4174 OUString aItem;
4176 if (m_pBox)
4178 UpdateFromColumn();
4179 weld::ComboBox& rBox = m_pBox->get_widget();
4180 aItem = rBox.get_active_text();
4183 return aItem;
4186 css::uno::Sequence<OUString> SAL_CALL FmXListBoxCell::getSelectedItems()
4188 ::osl::MutexGuard aGuard( m_aMutex );
4190 css::uno::Sequence<OUString> aSeq;
4192 if (m_pBox)
4194 UpdateFromColumn();
4195 weld::ComboBox& rBox = m_pBox->get_widget();
4196 auto nActive = rBox.get_active();
4197 if (nActive != -1)
4199 aSeq = css::uno::Sequence<OUString>(1);
4200 aSeq.getArray()[0] = rBox.get_text(nActive);
4203 return aSeq;
4206 void SAL_CALL FmXListBoxCell::selectItemPos(sal_Int16 nPos, sal_Bool bSelect)
4208 ::osl::MutexGuard aGuard( m_aMutex );
4210 if (m_pBox)
4212 weld::ComboBox& rBox = m_pBox->get_widget();
4213 if (bSelect)
4214 rBox.set_active(nPos);
4215 else if (nPos == rBox.get_active())
4216 rBox.set_active(-1);
4220 void SAL_CALL FmXListBoxCell::selectItemsPos(const Sequence< sal_Int16 >& aPositions, sal_Bool bSelect)
4222 ::osl::MutexGuard aGuard( m_aMutex );
4224 if (m_pBox)
4226 weld::ComboBox& rBox = m_pBox->get_widget();
4227 for ( sal_uInt16 n = static_cast<sal_uInt16>(aPositions.getLength()); n; )
4229 auto nPos = static_cast<sal_uInt16>(aPositions.getConstArray()[--n]);
4230 if (bSelect)
4231 rBox.set_active(nPos);
4232 else if (nPos == rBox.get_active())
4233 rBox.set_active(-1);
4238 void SAL_CALL FmXListBoxCell::selectItem(const OUString& aItem, sal_Bool bSelect)
4240 ::osl::MutexGuard aGuard( m_aMutex );
4242 if (m_pBox)
4244 weld::ComboBox& rBox = m_pBox->get_widget();
4245 auto nPos = rBox.find_text(aItem);
4246 if (bSelect)
4247 rBox.set_active(nPos);
4248 else if (nPos == rBox.get_active())
4249 rBox.set_active(-1);
4253 sal_Bool SAL_CALL FmXListBoxCell::isMutipleMode()
4255 ::osl::MutexGuard aGuard( m_aMutex );
4257 return m_bMulti;
4260 void SAL_CALL FmXListBoxCell::setMultipleMode(sal_Bool bMulti)
4262 ::osl::MutexGuard aGuard( m_aMutex );
4264 m_bMulti = bMulti;
4267 sal_Int16 SAL_CALL FmXListBoxCell::getDropDownLineCount()
4269 ::osl::MutexGuard aGuard( m_aMutex );
4270 return m_nLines;
4273 void SAL_CALL FmXListBoxCell::setDropDownLineCount(sal_Int16 nLines)
4275 ::osl::MutexGuard aGuard( m_aMutex );
4277 m_nLines = nLines; // just store it to return it
4280 void SAL_CALL FmXListBoxCell::makeVisible(sal_Int16 /*nEntry*/)
4284 IMPL_LINK(FmXListBoxCell, ChangedHdl, bool, bInteractive, void)
4286 if (!m_pBox)
4287 return;
4289 weld::ComboBox& rBox = m_pBox->get_widget();
4291 if (bInteractive && !rBox.changed_by_direct_pick())
4292 return;
4294 OnDoubleClick();
4296 css::awt::ItemEvent aEvent;
4297 aEvent.Source = *this;
4298 aEvent.Highlighted = 0;
4300 // with multiple selection 0xFFFF, otherwise the ID
4301 aEvent.Selected = (rBox.get_active() != -1 )
4302 ? rBox.get_active() : 0xFFFF;
4304 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
4307 void FmXListBoxCell::OnDoubleClick()
4309 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aActionListeners );
4311 css::awt::ActionEvent aEvent;
4312 aEvent.Source = *this;
4313 weld::ComboBox& rBox = m_pBox->get_widget();
4314 aEvent.ActionCommand = rBox.get_active_text();
4316 while( aIt.hasMoreElements() )
4317 static_cast< css::awt::XActionListener *>(aIt.next())->actionPerformed( aEvent );
4320 FmXComboBoxCell::FmXComboBoxCell( DbGridColumn* pColumn, std::unique_ptr<DbCellControl> pControl )
4321 :FmXTextCell( pColumn, std::move(pControl) )
4322 ,m_aItemListeners( m_aMutex )
4323 ,m_aActionListeners( m_aMutex )
4324 ,m_pComboBox(&static_cast<ComboBoxControl&>(m_pCellControl->GetWindow()))
4325 ,m_nLines(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount())
4327 m_pComboBox->SetAuxModifyHdl(LINK(this, FmXComboBoxCell, ChangedHdl));
4330 FmXComboBoxCell::~FmXComboBoxCell()
4332 if ( !OComponentHelper::rBHelper.bDisposed )
4334 acquire();
4335 dispose();
4340 void FmXComboBoxCell::disposing()
4342 css::lang::EventObject aEvt(*this);
4343 m_aItemListeners.disposeAndClear(aEvt);
4344 m_aActionListeners.disposeAndClear(aEvt);
4346 m_pComboBox->SetAuxModifyHdl(Link<bool,void>());
4347 m_pComboBox = nullptr;
4349 FmXTextCell::disposing();
4352 Any SAL_CALL FmXComboBoxCell::queryAggregation( const css::uno::Type& _rType )
4354 Any aReturn = FmXTextCell::queryAggregation(_rType);
4356 if ( !aReturn.hasValue() )
4357 aReturn = FmXComboBoxCell_Base::queryInterface( _rType );
4359 return aReturn;
4362 Sequence< Type > SAL_CALL FmXComboBoxCell::getTypes( )
4364 return ::comphelper::concatSequences(
4365 FmXTextCell::getTypes(),
4366 FmXComboBoxCell_Base::getTypes()
4370 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXComboBoxCell )
4372 void SAL_CALL FmXComboBoxCell::addItemListener(const Reference< awt::XItemListener >& l)
4374 m_aItemListeners.addInterface( l );
4377 void SAL_CALL FmXComboBoxCell::removeItemListener(const Reference< awt::XItemListener >& l)
4379 m_aItemListeners.removeInterface( l );
4382 void SAL_CALL FmXComboBoxCell::addActionListener(const Reference< awt::XActionListener >& l)
4384 m_aActionListeners.addInterface( l );
4388 void SAL_CALL FmXComboBoxCell::removeActionListener(const Reference< awt::XActionListener >& l)
4390 m_aActionListeners.removeInterface( l );
4393 void SAL_CALL FmXComboBoxCell::addItem( const OUString& Item, sal_Int16 Pos )
4395 ::osl::MutexGuard aGuard( m_aMutex );
4396 if (!m_pComboBox)
4397 return;
4398 weld::ComboBox& rBox = m_pComboBox->get_widget();
4399 rBox.insert_text(Pos, Item);
4402 void SAL_CALL FmXComboBoxCell::addItems( const Sequence< OUString >& Items, sal_Int16 Pos )
4404 ::osl::MutexGuard aGuard( m_aMutex );
4405 if (!m_pComboBox)
4406 return;
4407 weld::ComboBox& rBox = m_pComboBox->get_widget();
4408 sal_uInt16 nP = Pos;
4409 for ( const auto& rItem : Items )
4411 rBox.insert_text(nP, rItem);
4412 if ( Pos != -1 )
4413 nP++;
4417 void SAL_CALL FmXComboBoxCell::removeItems( sal_Int16 Pos, sal_Int16 Count )
4419 ::osl::MutexGuard aGuard( m_aMutex );
4420 if (!m_pComboBox)
4421 return;
4422 weld::ComboBox& rBox = m_pComboBox->get_widget();
4423 for ( sal_uInt16 n = Count; n; )
4424 rBox.remove( Pos + (--n) );
4427 sal_Int16 SAL_CALL FmXComboBoxCell::getItemCount()
4429 ::osl::MutexGuard aGuard( m_aMutex );
4430 if (!m_pComboBox)
4431 return 0;
4432 weld::ComboBox& rBox = m_pComboBox->get_widget();
4433 return rBox.get_count();
4436 OUString SAL_CALL FmXComboBoxCell::getItem( sal_Int16 Pos )
4438 ::osl::MutexGuard aGuard( m_aMutex );
4439 if (!m_pComboBox)
4440 return OUString();
4441 weld::ComboBox& rBox = m_pComboBox->get_widget();
4442 return rBox.get_text(Pos);
4445 Sequence< OUString > SAL_CALL FmXComboBoxCell::getItems()
4447 ::osl::MutexGuard aGuard( m_aMutex );
4449 Sequence< OUString > aItems;
4450 if (m_pComboBox)
4452 weld::ComboBox& rBox = m_pComboBox->get_widget();
4453 const sal_Int32 nEntries = rBox.get_count();
4454 aItems.realloc( nEntries );
4455 OUString* pItem = aItems.getArray();
4456 for ( sal_Int32 n=0; n<nEntries; ++n, ++pItem )
4457 *pItem = rBox.get_text(n);
4459 return aItems;
4462 sal_Int16 SAL_CALL FmXComboBoxCell::getDropDownLineCount()
4464 ::osl::MutexGuard aGuard( m_aMutex );
4465 return m_nLines;
4468 void SAL_CALL FmXComboBoxCell::setDropDownLineCount(sal_Int16 nLines)
4470 ::osl::MutexGuard aGuard( m_aMutex );
4471 m_nLines = nLines; // just store it to return it
4474 IMPL_LINK(FmXComboBoxCell, ChangedHdl, bool, bInteractive, void)
4476 if (!m_pComboBox)
4477 return;
4479 weld::ComboBox& rComboBox = m_pComboBox->get_widget();
4481 if (bInteractive && !rComboBox.changed_by_direct_pick())
4482 return;
4484 awt::ItemEvent aEvent;
4485 aEvent.Source = *this;
4486 aEvent.Highlighted = 0;
4488 // with invalid selection 0xFFFF, otherwise the position
4489 aEvent.Selected = ( rComboBox.get_active() != -1 )
4490 ? rComboBox.get_active()
4491 : 0xFFFF;
4492 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
4495 FmXFilterCell::FmXFilterCell(DbGridColumn* pColumn, std::unique_ptr<DbFilterField> pControl )
4496 :FmXGridCell( pColumn, std::move(pControl) )
4497 ,m_aTextListeners(m_aMutex)
4499 static_cast<DbFilterField*>(m_pCellControl.get())->SetCommitHdl( LINK( this, FmXFilterCell, OnCommit ) );
4502 FmXFilterCell::~FmXFilterCell()
4504 if (!OComponentHelper::rBHelper.bDisposed)
4506 acquire();
4507 dispose();
4512 // XUnoTunnel
4513 sal_Int64 SAL_CALL FmXFilterCell::getSomething( const Sequence< sal_Int8 >& _rIdentifier )
4515 sal_Int64 nReturn(0);
4517 if ( isUnoTunnelId<FmXFilterCell>(_rIdentifier) )
4519 nReturn = reinterpret_cast<sal_Int64>(this);
4522 return nReturn;
4525 namespace
4527 class theFmXFilterCellUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theFmXFilterCellUnoTunnelId > {};
4530 const Sequence<sal_Int8>& FmXFilterCell::getUnoTunnelId()
4532 return theFmXFilterCellUnoTunnelId::get().getSeq();
4536 void FmXFilterCell::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect )
4538 static_cast< DbFilterField* >( m_pCellControl.get() )->PaintCell( rDev, rRect );
4541 // OComponentHelper
4543 void FmXFilterCell::disposing()
4545 css::lang::EventObject aEvt(*this);
4546 m_aTextListeners.disposeAndClear(aEvt);
4548 static_cast<DbFilterField*>(m_pCellControl.get())->SetCommitHdl(Link<DbFilterField&,void>());
4550 FmXGridCell::disposing();
4554 Any SAL_CALL FmXFilterCell::queryAggregation( const css::uno::Type& _rType )
4556 Any aReturn = FmXGridCell::queryAggregation(_rType);
4558 if ( !aReturn.hasValue() )
4559 aReturn = FmXFilterCell_Base::queryInterface( _rType );
4561 return aReturn;
4565 Sequence< css::uno::Type > SAL_CALL FmXFilterCell::getTypes( )
4567 return ::comphelper::concatSequences(
4568 FmXGridCell::getTypes(),
4569 FmXFilterCell_Base::getTypes()
4574 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXFilterCell )
4576 // css::awt::XTextComponent
4578 void SAL_CALL FmXFilterCell::addTextListener(const Reference< css::awt::XTextListener >& l)
4580 m_aTextListeners.addInterface( l );
4584 void SAL_CALL FmXFilterCell::removeTextListener(const Reference< css::awt::XTextListener >& l)
4586 m_aTextListeners.removeInterface( l );
4589 void SAL_CALL FmXFilterCell::setText( const OUString& aText )
4591 ::osl::MutexGuard aGuard( m_aMutex );
4592 static_cast<DbFilterField*>(m_pCellControl.get())->SetText(aText);
4595 void SAL_CALL FmXFilterCell::insertText( const css::awt::Selection& /*rSel*/, const OUString& /*aText*/ )
4599 OUString SAL_CALL FmXFilterCell::getText()
4601 ::osl::MutexGuard aGuard( m_aMutex );
4602 return static_cast<DbFilterField*>(m_pCellControl.get())->GetText();
4605 OUString SAL_CALL FmXFilterCell::getSelectedText()
4607 return getText();
4610 void SAL_CALL FmXFilterCell::setSelection( const css::awt::Selection& /*aSelection*/ )
4614 css::awt::Selection SAL_CALL FmXFilterCell::getSelection()
4616 return css::awt::Selection();
4619 sal_Bool SAL_CALL FmXFilterCell::isEditable()
4621 return true;
4624 void SAL_CALL FmXFilterCell::setEditable( sal_Bool /*bEditable*/ )
4628 sal_Int16 SAL_CALL FmXFilterCell::getMaxTextLen()
4630 return 0;
4633 void SAL_CALL FmXFilterCell::setMaxTextLen( sal_Int16 /*nLen*/ )
4637 IMPL_LINK_NOARG(FmXFilterCell, OnCommit, DbFilterField&, void)
4639 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aTextListeners );
4640 css::awt::TextEvent aEvt;
4641 aEvt.Source = *this;
4642 while( aIt.hasMoreElements() )
4643 static_cast< css::awt::XTextListener *>(aIt.next())->textChanged( aEvt );
4646 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */