Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / svx / source / fmcomp / gridcell.cxx
blobc52e4764da5d8b085965be9e115ca7252433daac
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <memory>
22 #include <sal/macros.h>
23 #include "fmprop.hrc"
24 #include "svx/fmresids.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/XNamed.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/sdb/XSQLQueryComposerFactory.hpp>
39 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
40 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
41 #include <com/sun/star/sdbc/ColumnValue.hpp>
42 #include <com/sun/star/sdbc/DataType.hpp>
43 #include <com/sun/star/sdbc/XStatement.hpp>
44 #include <com/sun/star/util/NumberFormat.hpp>
45 #include <com/sun/star/util/XNumberFormatsSupplier.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 <connectivity/formattedcolumnvalue.hxx>
54 #include <cppuhelper/typeprovider.hxx>
55 #include <i18nlangtag/lang.h>
56 #include <o3tl/make_unique.hxx>
58 #include <rtl/math.hxx>
59 #include <svtools/calendar.hxx>
60 #include <svtools/fmtfield.hxx>
61 #include <svl/numuno.hxx>
62 #include <svtools/svmedit.hxx>
63 #include <svx/dialmgr.hxx>
64 #include <toolkit/helper/vclunohelper.hxx>
65 #include <tools/diagnose_ex.h>
66 #include <vcl/longcurr.hxx>
67 #include <vcl/settings.hxx>
68 #include <connectivity/dbtools.hxx>
69 #include <connectivity/dbconversion.hxx>
70 #include <connectivity/sqlnode.hxx>
72 #include <math.h>
74 using namespace ::connectivity;
75 using namespace ::svxform;
76 using namespace ::comphelper;
77 using namespace ::svt;
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::sdbc;
81 using namespace ::com::sun::star::sdbcx;
82 using namespace ::com::sun::star::sdb;
83 using namespace ::com::sun::star::beans;
84 using namespace ::com::sun::star::form;
85 using namespace ::dbtools::DBTypeConversion;
86 using namespace ::dbtools;
88 using ::com::sun::star::util::XNumberFormatter;
90 const char INVALIDTEXT[] = "###";
91 const char OBJECTTEXT[] = "<OBJECT>";
94 //= helper
96 namespace
98 LineEnd getModelLineEndSetting( const Reference< XPropertySet >& _rxModel )
100 LineEnd eFormat = LINEEND_LF;
104 sal_Int16 nLineEndFormat = awt::LineEndFormat::LINE_FEED;
106 Reference< XPropertySetInfo > xPSI;
107 if ( _rxModel.is() )
108 xPSI = _rxModel->getPropertySetInfo();
110 OSL_ENSURE( xPSI.is(), "getModelLineEndSetting: invalid column model!" );
111 if ( xPSI.is() && xPSI->hasPropertyByName( FM_PROP_LINEENDFORMAT ) )
113 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_LINEENDFORMAT ) >>= nLineEndFormat );
115 switch ( nLineEndFormat )
117 case awt::LineEndFormat::CARRIAGE_RETURN: eFormat = LINEEND_CR; break;
118 case awt::LineEndFormat::LINE_FEED: eFormat = LINEEND_LF; break;
119 case awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED: eFormat = LINEEND_CRLF; break;
120 default:
121 OSL_FAIL( "getModelLineEndSetting: what's this?" );
125 catch( const Exception& )
127 OSL_FAIL( "getModelLineEndSetting: caught an exception!" );
128 DBG_UNHANDLED_EXCEPTION();
130 return eFormat;
135 //= DbGridColumn
138 CellControllerRef DbGridColumn::s_xEmptyController;
141 void DbGridColumn::CreateControl(sal_Int32 _nFieldPos, const Reference< css::beans::XPropertySet >& xField, sal_Int32 nTypeId)
143 Clear();
145 m_nTypeId = (sal_Int16)nTypeId;
146 if (xField != m_xField)
148 // initial setting
149 m_xField = xField;
150 xField->getPropertyValue(FM_PROP_FORMATKEY) >>= m_nFormatKey;
151 m_nFieldPos = (sal_Int16)_nFieldPos;
152 m_bReadOnly = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISREADONLY));
153 m_bAutoValue = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_AUTOINCREMENT));
154 m_nFieldType = (sal_Int16)::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE));
156 switch (m_nFieldType)
158 case DataType::DATE:
159 case DataType::TIME:
160 case DataType::TIMESTAMP:
161 m_bDateTime = true;
162 SAL_FALLTHROUGH;
163 case DataType::BIT:
164 case DataType::BOOLEAN:
165 case DataType::TINYINT:
166 case DataType::SMALLINT:
167 case DataType::INTEGER:
168 case DataType::BIGINT:
169 case DataType::FLOAT:
170 case DataType::REAL:
171 case DataType::DOUBLE:
172 case DataType::NUMERIC:
173 case DataType::DECIMAL:
174 m_nAlign = css::awt::TextAlign::RIGHT;
175 m_bNumeric = true;
176 break;
177 default:
178 m_nAlign = css::awt::TextAlign::LEFT;
179 break;
183 DbCellControl* pCellControl = nullptr;
184 if (m_rParent.IsFilterMode())
186 pCellControl = new DbFilterField(m_rParent.getContext(),*this);
188 else
191 switch (nTypeId)
193 case TYPE_CHECKBOX: pCellControl = new DbCheckBox(*this); break;
194 case TYPE_COMBOBOX: pCellControl = new DbComboBox(*this); break;
195 case TYPE_CURRENCYFIELD: pCellControl = new DbCurrencyField(*this); break;
196 case TYPE_DATEFIELD: pCellControl = new DbDateField(*this); break;
197 case TYPE_LISTBOX: pCellControl = new DbListBox(*this); break;
198 case TYPE_NUMERICFIELD: pCellControl = new DbNumericField(*this); break;
199 case TYPE_PATTERNFIELD: pCellControl = new DbPatternField( *this, m_rParent.getContext() ); break;
200 case TYPE_TEXTFIELD: pCellControl = new DbTextField(*this); break;
201 case TYPE_TIMEFIELD: pCellControl = new DbTimeField(*this); break;
202 case TYPE_FORMATTEDFIELD: pCellControl = new DbFormattedField(*this); break;
203 default:
204 OSL_FAIL("DbGridColumn::CreateControl: Unknown Column");
205 return;
209 Reference< XRowSet > xCur;
210 if (m_rParent.getDataSource())
211 xCur.set(Reference< XInterface >(*m_rParent.getDataSource()), UNO_QUERY);
212 // TODO : the cursor wrapper should use an XRowSet interface, too
214 pCellControl->Init( m_rParent.GetDataWindow(), xCur );
216 // now create the control wrapper
217 if (m_rParent.IsFilterMode())
218 m_pCell = new FmXFilterCell(this, pCellControl);
219 else
221 switch (nTypeId)
223 case TYPE_CHECKBOX: m_pCell = new FmXCheckBoxCell( this, *pCellControl ); break;
224 case TYPE_LISTBOX: m_pCell = new FmXListBoxCell( this, *pCellControl ); break;
225 case TYPE_COMBOBOX: m_pCell = new FmXComboBoxCell( this, *pCellControl ); break;
226 default:
227 m_pCell = new FmXEditCell( this, *pCellControl );
230 m_pCell->init();
232 impl_toggleScriptManager_nothrow( true );
234 // only if we use have a bound field, we use a controller for displaying the
235 // window in the grid
236 if (m_xField.is())
237 m_xController = pCellControl->CreateController();
241 void DbGridColumn::impl_toggleScriptManager_nothrow( bool _bAttach )
245 Reference< container::XChild > xChild( m_xModel, UNO_QUERY_THROW );
246 Reference< script::XEventAttacherManager > xManager( xChild->getParent(), UNO_QUERY_THROW );
247 Reference< container::XIndexAccess > xContainer( xChild->getParent(), UNO_QUERY_THROW );
249 sal_Int32 nIndexInParent( getElementPos( xContainer, m_xModel ) );
251 Reference< XInterface > xCellInterface( *m_pCell, UNO_QUERY );
252 if ( _bAttach )
253 xManager->attach( nIndexInParent, xCellInterface, makeAny( xCellInterface ) );
254 else
255 xManager->detach( nIndexInParent, xCellInterface );
257 catch( const Exception& )
259 DBG_UNHANDLED_EXCEPTION();
263 void DbGridColumn::UpdateFromField(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter)
265 if (FmXFilterCell* pCell = dynamic_cast<FmXFilterCell*>(m_pCell.get()))
266 pCell->Update();
267 else if (pRow && pRow->IsValid() && m_nFieldPos >= 0 && m_pCell.is() && pRow->HasField(m_nFieldPos))
269 dynamic_cast<FmXDataCell&>(*m_pCell).UpdateFromField( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter );
273 bool DbGridColumn::Commit()
275 bool bResult = true;
276 if (!m_bInSave && m_pCell.is())
278 m_bInSave = true;
279 bResult = m_pCell->Commit();
281 // store the data into the model
282 FmXDataCell* pDataCell = dynamic_cast<FmXDataCell*>( m_pCell.get() );
283 if (bResult && pDataCell)
285 Reference< css::form::XBoundComponent > xComp(m_xModel, UNO_QUERY);
286 if (xComp.is())
287 bResult = xComp->commit();
289 m_bInSave = false;
291 return bResult;
295 DbGridColumn::~DbGridColumn()
297 Clear();
301 void DbGridColumn::setModel(const css::uno::Reference< css::beans::XPropertySet >& _xModel)
303 if ( m_pCell.is() )
304 impl_toggleScriptManager_nothrow( false );
306 m_xModel = _xModel;
308 if ( m_pCell.is() )
309 impl_toggleScriptManager_nothrow( true );
313 void DbGridColumn::Clear()
315 if ( m_pCell.is() )
317 impl_toggleScriptManager_nothrow( false );
319 m_pCell->dispose();
320 m_pCell.clear();
323 m_xController = nullptr;
324 m_xField = nullptr;
326 m_nFormatKey = 0;
327 m_nFieldPos = -1;
328 m_bReadOnly = true;
329 m_bAutoValue = false;
330 m_nFieldType = DataType::OTHER;
334 sal_Int16 DbGridColumn::SetAlignment(sal_Int16 _nAlign)
336 if (_nAlign == -1)
337 { // 'Standard'
338 if (m_xField.is())
340 sal_Int32 nType = 0;
341 m_xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nType;
343 switch (nType)
345 case DataType::NUMERIC:
346 case DataType::DECIMAL:
347 case DataType::DOUBLE:
348 case DataType::REAL:
349 case DataType::BIGINT:
350 case DataType::INTEGER:
351 case DataType::SMALLINT:
352 case DataType::TINYINT:
353 case DataType::DATE:
354 case DataType::TIME:
355 case DataType::TIMESTAMP:
356 _nAlign = css::awt::TextAlign::RIGHT;
357 break;
358 case DataType::BIT:
359 case DataType::BOOLEAN:
360 _nAlign = css::awt::TextAlign::CENTER;
361 break;
362 default:
363 _nAlign = css::awt::TextAlign::LEFT;
364 break;
367 else
368 _nAlign = css::awt::TextAlign::LEFT;
371 m_nAlign = _nAlign;
372 if (m_pCell.is() && m_pCell->isAlignedController())
373 m_pCell->AlignControl(m_nAlign);
375 return m_nAlign;
379 sal_Int16 DbGridColumn::SetAlignmentFromModel(sal_Int16 nStandardAlign)
381 Any aAlign( m_xModel->getPropertyValue(FM_PROP_ALIGN));
382 if (aAlign.hasValue())
384 sal_Int16 nTest = sal_Int16();
385 if (aAlign >>= nTest)
386 nStandardAlign = nTest;
388 return SetAlignment(nStandardAlign);
392 void DbGridColumn::setLock(bool _bLock)
394 if (m_bLocked == _bLock)
395 return;
396 m_bLocked = _bLock;
398 // is the column we represent active ?
399 if (m_bHidden)
400 return; // no, it isn't (or at least it shouldn't be ...)
402 if (m_rParent.GetCurColumnId() == m_nId)
404 m_rParent.DeactivateCell();
405 m_rParent.ActivateCell(m_rParent.GetCurRow(), m_rParent.GetCurColumnId());
410 OUString DbGridColumn::GetCellText(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter) const
412 OUString aText;
413 if (m_pCell.is() && dynamic_cast<const FmXFilterCell*>( m_pCell.get() ) != nullptr)
414 return aText;
416 if (!pRow || !pRow->IsValid())
417 aText = INVALIDTEXT;
418 else if (pRow->HasField(m_nFieldPos))
420 aText = GetCellText( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter );
422 return aText;
426 OUString DbGridColumn::GetCellText(const Reference< css::sdb::XColumn >& xField, const Reference< XNumberFormatter >& xFormatter) const
428 OUString aText;
429 if (xField.is())
431 FmXTextCell* pTextCell = dynamic_cast<FmXTextCell*>( m_pCell.get() );
432 if (pTextCell)
433 aText = pTextCell->GetText(xField, xFormatter);
434 else if (m_bObject)
435 aText = OBJECTTEXT;
437 return aText;
441 Reference< css::sdb::XColumn > DbGridColumn::GetCurrentFieldValue() const
443 Reference< css::sdb::XColumn > xField;
444 const DbGridRowRef xRow = m_rParent.GetCurrentRow();
445 if (xRow.is() && xRow->HasField(m_nFieldPos))
447 xField = xRow->GetField(m_nFieldPos).getColumn();
449 return xField;
453 void DbGridColumn::Paint(OutputDevice& rDev,
454 const tools::Rectangle& rRect,
455 const DbGridRow* pRow,
456 const Reference< XNumberFormatter >& xFormatter)
458 bool bEnabled = ( rDev.GetOutDevType() != OUTDEV_WINDOW )
459 || ( static_cast< vcl::Window& >( rDev ).IsEnabled() );
461 FmXDataCell* pDataCell = dynamic_cast<FmXDataCell*>( m_pCell.get() );
462 if (pDataCell)
464 if (!pRow || !pRow->IsValid())
466 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
467 if ( !bEnabled )
468 nStyle |= DrawTextFlags::Disable;
470 rDev.DrawText(rRect, OUString(INVALIDTEXT), nStyle);
472 else if (m_bAutoValue && pRow->IsNew())
474 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter;
475 if ( !bEnabled )
476 nStyle |= DrawTextFlags::Disable;
478 switch (GetAlignment())
480 case css::awt::TextAlign::RIGHT:
481 nStyle |= DrawTextFlags::Right;
482 break;
483 case css::awt::TextAlign::CENTER:
484 nStyle |= DrawTextFlags::Center;
485 break;
486 default:
487 nStyle |= DrawTextFlags::Left;
490 rDev.DrawText(rRect, SvxResId(RID_STR_AUTOFIELD), nStyle);
492 else if (pRow->HasField(m_nFieldPos))
494 pDataCell->PaintFieldToCell(rDev, rRect, pRow->GetField( m_nFieldPos ).getColumn(), xFormatter);
497 else if (!m_pCell.is())
499 if (!pRow || !pRow->IsValid())
501 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
502 if ( !bEnabled )
503 nStyle |= DrawTextFlags::Disable;
505 rDev.DrawText(rRect, OUString(INVALIDTEXT), nStyle);
507 else if (pRow->HasField(m_nFieldPos) && m_bObject)
509 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center;
510 if ( !bEnabled )
511 nStyle |= DrawTextFlags::Disable;
512 rDev.DrawText(rRect, OUString(OBJECTTEXT), nStyle);
515 else if ( dynamic_cast<const FmXFilterCell*>( m_pCell.get() ) != nullptr )
516 static_cast< FmXFilterCell* >( m_pCell.get() )->PaintCell( rDev, rRect );
520 void DbGridColumn::ImplInitWindow( vcl::Window& rParent, const InitWindowFacet _eInitWhat )
522 if ( m_pCell.is() )
523 m_pCell->ImplInitWindow( rParent, _eInitWhat );
527 //= cell controls
530 DbCellControl::DbCellControl( DbGridColumn& _rColumn )
531 :OPropertyChangeListener(m_aMutex)
532 ,m_bTransparent( false )
533 ,m_bAlignedController( true )
534 ,m_bAccessingValueProperty( false )
535 ,m_rColumn( _rColumn )
536 ,m_pPainter( nullptr )
537 ,m_pWindow( nullptr )
539 Reference< XPropertySet > xColModelProps( _rColumn.getModel(), UNO_QUERY );
540 if ( xColModelProps.is() )
542 // if our model's format key changes we want to propagate the new value to our windows
543 m_pModelChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, Reference< css::beans::XPropertySet > (_rColumn.getModel(), UNO_QUERY));
545 // be listener for some common properties
546 implDoPropertyListening( FM_PROP_READONLY, false );
547 implDoPropertyListening( FM_PROP_ENABLED, false );
549 // add as listener for all known "value" properties
550 implDoPropertyListening( FM_PROP_VALUE, false );
551 implDoPropertyListening( FM_PROP_STATE, false );
552 implDoPropertyListening( FM_PROP_TEXT, false );
553 implDoPropertyListening( FM_PROP_EFFECTIVE_VALUE, false );
554 implDoPropertyListening( FM_PROP_SELECT_SEQ, false );
555 implDoPropertyListening( FM_PROP_DATE, false );
556 implDoPropertyListening( FM_PROP_TIME, false );
558 // be listener at the bound field as well
561 Reference< XPropertySetInfo > xPSI( xColModelProps->getPropertySetInfo(), UNO_SET_THROW );
562 if ( xPSI->hasPropertyByName( FM_PROP_BOUNDFIELD ) )
564 Reference< XPropertySet > xField;
565 xColModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
566 if ( xField.is() )
568 m_pFieldChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, xField);
569 m_pFieldChangeBroadcaster->addProperty( FM_PROP_ISREADONLY );
573 catch( const Exception& )
575 OSL_FAIL( "DbCellControl::doPropertyListening: caught an exception!" );
576 DBG_UNHANDLED_EXCEPTION();
582 void DbCellControl::implDoPropertyListening(const OUString& _rPropertyName, bool _bWarnIfNotExistent)
586 Reference< XPropertySet > xColModelProps( m_rColumn.getModel(), UNO_QUERY );
587 Reference< XPropertySetInfo > xPSI;
588 if ( xColModelProps.is() )
589 xPSI = xColModelProps->getPropertySetInfo();
591 DBG_ASSERT( !_bWarnIfNotExistent || ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) ),
592 "DbCellControl::doPropertyListening: no property set info or non-existent property!" );
593 (void)_bWarnIfNotExistent;
595 if ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) )
596 m_pModelChangeBroadcaster->addProperty( _rPropertyName );
598 catch( const Exception& )
600 OSL_FAIL( "DbCellControl::doPropertyListening: caught an exception!" );
601 DBG_UNHANDLED_EXCEPTION();
606 void DbCellControl::doPropertyListening(const OUString& _rPropertyName)
608 implDoPropertyListening( _rPropertyName, true );
611 static void lcl_clearBroadCaster(rtl::Reference<::comphelper::OPropertyChangeMultiplexer>& _pBroadcaster)
613 if ( _pBroadcaster.is() )
615 _pBroadcaster->dispose();
616 _pBroadcaster.clear();
617 // no delete, this is done implicitly
621 DbCellControl::~DbCellControl()
623 lcl_clearBroadCaster(m_pModelChangeBroadcaster);
624 lcl_clearBroadCaster(m_pFieldChangeBroadcaster);
626 m_pWindow.disposeAndClear();
627 m_pPainter.disposeAndClear();
630 void DbCellControl::implValuePropertyChanged( )
632 OSL_ENSURE( !isValuePropertyLocked(),
633 "DbCellControl::implValuePropertyChanged: not to be called with the value property locked!" );
635 if ( m_pWindow )
637 if ( m_rColumn.getModel().is() )
638 updateFromModel( m_rColumn.getModel() );
643 void DbCellControl::implAdjustGenericFieldSetting( const Reference< XPropertySet >& /*_rxModel*/ )
645 // nothing to do here
649 void DbCellControl::_propertyChanged(const PropertyChangeEvent& _rEvent)
651 SolarMutexGuard aGuard;
653 Reference< XPropertySet > xSourceProps( _rEvent.Source, UNO_QUERY );
655 if ( _rEvent.PropertyName == FM_PROP_VALUE
656 || _rEvent.PropertyName == FM_PROP_STATE
657 || _rEvent.PropertyName == FM_PROP_TEXT
658 || _rEvent.PropertyName == FM_PROP_EFFECTIVE_VALUE
659 || _rEvent.PropertyName == FM_PROP_SELECT_SEQ
660 || _rEvent.PropertyName == FM_PROP_DATE
661 || _rEvent.PropertyName == FM_PROP_TIME
663 { // it was one of the known "value" properties
664 if ( !isValuePropertyLocked() )
666 implValuePropertyChanged( );
669 else if ( _rEvent.PropertyName == FM_PROP_READONLY )
671 implAdjustReadOnly( xSourceProps, true);
673 else if ( _rEvent.PropertyName == FM_PROP_ISREADONLY )
675 bool bReadOnly = true;
676 _rEvent.NewValue >>= bReadOnly;
677 m_rColumn.SetReadOnly(bReadOnly);
678 implAdjustReadOnly( xSourceProps, false);
680 else if ( _rEvent.PropertyName == FM_PROP_ENABLED )
682 implAdjustEnabled( xSourceProps );
684 else
685 implAdjustGenericFieldSetting( xSourceProps );
689 bool DbCellControl::Commit()
691 // lock the listening for value property changes
692 lockValueProperty();
693 // commit the content of the control into the model's value property
694 bool bReturn = false;
697 bReturn = commitControl();
699 catch( const Exception& )
701 DBG_UNHANDLED_EXCEPTION();
703 // unlock the listening for value property changes
704 unlockValueProperty();
705 // outta here
706 return bReturn;
710 void DbCellControl::ImplInitWindow( vcl::Window& rParent, const InitWindowFacet _eInitWhat )
712 vcl::Window* pWindows[] = { m_pPainter, m_pWindow };
714 if (_eInitWhat & InitWindowFacet::WritingMode)
716 for (vcl::Window* pWindow : pWindows)
718 if (pWindow)
719 pWindow->EnableRTL(rParent.IsRTLEnabled());
723 if (_eInitWhat & InitWindowFacet::Font)
725 for (vcl::Window* pWindow : pWindows)
727 if (!pWindow)
728 continue;
730 pWindow->SetZoom(rParent.GetZoom());
732 const StyleSettings& rStyleSettings = pWindow->GetSettings().GetStyleSettings();
733 vcl::Font aFont = rStyleSettings.GetFieldFont();
734 aFont.SetTransparent(isTransparent());
736 if (rParent.IsControlFont())
738 pWindow->SetControlFont(rParent.GetControlFont());
739 aFont.Merge(rParent.GetControlFont());
741 else
742 pWindow->SetControlFont();
744 pWindow->SetZoomedPointFont(*pWindow, aFont); // FIXME RenderContext
748 if ((_eInitWhat & InitWindowFacet::Font) || (_eInitWhat & InitWindowFacet::Foreground))
750 Color aTextColor(rParent.IsControlForeground() ? rParent.GetControlForeground() : rParent.GetTextColor());
752 bool bTextLineColor = rParent.IsTextLineColor();
753 Color aTextLineColor(rParent.GetTextLineColor());
755 for (vcl::Window* pWindow : pWindows)
757 if (pWindow)
759 pWindow->SetTextColor(aTextColor);
760 if (rParent.IsControlForeground())
761 pWindow->SetControlForeground(aTextColor);
763 if (bTextLineColor)
764 pWindow->SetTextLineColor();
765 else
766 pWindow->SetTextLineColor(aTextLineColor);
771 if (_eInitWhat & InitWindowFacet::Background)
773 if (rParent.IsControlBackground())
775 Color aColor(rParent.GetControlBackground());
776 for (vcl::Window* pWindow : pWindows)
778 if (pWindow)
780 if (isTransparent())
781 pWindow->SetBackground();
782 else
784 pWindow->SetBackground(aColor);
785 pWindow->SetControlBackground(aColor);
787 pWindow->SetFillColor(aColor);
791 else
793 if (m_pPainter)
795 if (isTransparent())
796 m_pPainter->SetBackground();
797 else
798 m_pPainter->SetBackground(rParent.GetBackground());
799 m_pPainter->SetFillColor(rParent.GetFillColor());
802 if (m_pWindow)
804 if (isTransparent())
805 m_pWindow->SetBackground(rParent.GetBackground());
806 else
807 m_pWindow->SetFillColor(rParent.GetFillColor());
814 void DbCellControl::implAdjustReadOnly( const Reference< XPropertySet >& _rxModel,bool i_bReadOnly )
816 DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustReadOnly: not to be called without window!" );
817 DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustReadOnly: invalid model!" );
818 if ( m_pWindow && _rxModel.is() )
820 Edit* pEditWindow = dynamic_cast< Edit* >( m_pWindow.get() );
821 if ( pEditWindow )
823 bool bReadOnly = m_rColumn.IsReadOnly();
824 if ( !bReadOnly )
826 _rxModel->getPropertyValue( i_bReadOnly ? OUString(FM_PROP_READONLY) : OUString(FM_PROP_ISREADONLY)) >>= bReadOnly;
828 static_cast< Edit* >( m_pWindow.get() )->SetReadOnly( bReadOnly );
834 void DbCellControl::implAdjustEnabled( const Reference< XPropertySet >& _rxModel )
836 DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustEnabled: not to be called without window!" );
837 DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustEnabled: invalid model!" );
838 if ( m_pWindow && _rxModel.is() )
840 bool bEnable = true;
841 _rxModel->getPropertyValue( FM_PROP_ENABLED ) >>= bEnable;
842 m_pWindow->Enable( bEnable );
847 void DbCellControl::Init( vcl::Window& rParent, const Reference< XRowSet >& _rxCursor )
849 ImplInitWindow( rParent, InitWindowFacet::All );
851 if ( m_pWindow )
853 // align the control
854 if ( isAlignedController() )
855 AlignControl( m_rColumn.GetAlignment() );
859 // some other common properties
860 Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW );
861 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
863 if ( xModelPSI->hasPropertyByName( FM_PROP_READONLY ) )
865 implAdjustReadOnly( xModel,true );
868 if ( xModelPSI->hasPropertyByName( FM_PROP_ENABLED ) )
870 implAdjustEnabled( xModel );
873 if ( xModelPSI->hasPropertyByName( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) )
875 sal_Int16 nWheelBehavior = css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY;
876 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) >>= nWheelBehavior );
877 MouseWheelBehaviour nVclSetting = MouseWheelBehaviour::FocusOnly;
878 switch ( nWheelBehavior )
880 case css::awt::MouseWheelBehavior::SCROLL_DISABLED: nVclSetting = MouseWheelBehaviour::Disable; break;
881 case css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY: nVclSetting = MouseWheelBehaviour::FocusOnly; break;
882 case css::awt::MouseWheelBehavior::SCROLL_ALWAYS: nVclSetting = MouseWheelBehaviour::ALWAYS; break;
883 default:
884 OSL_FAIL( "DbCellControl::Init: invalid MouseWheelBehavior!" );
885 break;
888 AllSettings aSettings = m_pWindow->GetSettings();
889 MouseSettings aMouseSettings = aSettings.GetMouseSettings();
890 aMouseSettings.SetWheelBehavior( nVclSetting );
891 aSettings.SetMouseSettings( aMouseSettings );
892 m_pWindow->SetSettings( aSettings, true );
895 catch( const Exception& )
897 DBG_UNHANDLED_EXCEPTION();
900 m_xCursor = _rxCursor;
901 if ( m_rColumn.getModel().is() )
902 updateFromModel( m_rColumn.getModel() );
906 void DbCellControl::SetTextLineColor()
908 if (m_pWindow)
909 m_pWindow->SetTextLineColor();
910 if (m_pPainter)
911 m_pPainter->SetTextLineColor();
915 void DbCellControl::SetTextLineColor(const Color& _rColor)
917 if (m_pWindow)
918 m_pWindow->SetTextLineColor(_rColor);
919 if (m_pPainter)
920 m_pPainter->SetTextLineColor(_rColor);
923 namespace
925 void lcl_implAlign( vcl::Window* _pWindow, WinBits _nAlignmentBit )
927 WinBits nStyle = _pWindow->GetStyle();
928 nStyle &= ~(WB_LEFT | WB_RIGHT | WB_CENTER);
929 _pWindow->SetStyle( nStyle | _nAlignmentBit );
934 void DbCellControl::AlignControl(sal_Int16 nAlignment)
936 WinBits nAlignmentBit = 0;
937 switch (nAlignment)
939 case css::awt::TextAlign::RIGHT:
940 nAlignmentBit = WB_RIGHT;
941 break;
942 case css::awt::TextAlign::CENTER:
943 nAlignmentBit = WB_CENTER;
944 break;
945 default:
946 nAlignmentBit = WB_LEFT;
947 break;
949 lcl_implAlign( m_pWindow, nAlignmentBit );
950 if ( m_pPainter )
951 lcl_implAlign( m_pPainter, nAlignmentBit );
955 void DbCellControl::PaintCell( OutputDevice& _rDev, const tools::Rectangle& _rRect )
957 if ( m_pPainter->GetParent() == &_rDev )
959 m_pPainter->SetPaintTransparent( true );
960 m_pPainter->SetBackground( );
961 m_pPainter->SetControlBackground( _rDev.GetFillColor() );
962 m_pPainter->SetControlForeground( _rDev.GetTextColor() );
963 m_pPainter->SetTextColor( _rDev.GetTextColor() );
964 m_pPainter->SetTextFillColor( _rDev.GetTextColor() );
966 vcl::Font aFont( _rDev.GetFont() );
967 aFont.SetTransparent( true );
968 m_pPainter->SetFont( aFont );
970 m_pPainter->SetPosSizePixel( _rRect.TopLeft(), _rRect.GetSize() );
971 m_pPainter->Show();
972 m_pPainter->Update();
973 m_pPainter->SetParentUpdateMode( false );
974 m_pPainter->Hide();
975 m_pPainter->SetParentUpdateMode( true );
977 else
978 m_pPainter->Draw( &_rDev, _rRect.TopLeft(), _rRect.GetSize(), DrawFlags::NONE );
982 void DbCellControl::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
984 m_pPainter->SetText( GetFormatText( _rxField, _rxFormatter ) );
985 PaintCell( _rDev, _rRect );
989 double DbCellControl::GetValue(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) const
991 double fValue = 0;
992 if (m_rColumn.IsNumeric())
996 fValue = _rxField->getDouble();
998 catch(const Exception&) { }
1000 else
1002 bool bSuccess = false;
1005 fValue = _rxField->getDouble();
1006 bSuccess = true;
1008 catch(const Exception&) { }
1009 if (!bSuccess)
1013 fValue = xFormatter->convertStringToNumber(m_rColumn.GetKey(), _rxField->getString());
1015 catch(const Exception&) { }
1018 return fValue;
1022 void DbCellControl::invalidatedController()
1024 m_rColumn.GetParent().refreshController(m_rColumn.GetId(), DbGridControl::GrantControlAccess());
1027 // CellModels
1029 DbLimitedLengthField::DbLimitedLengthField( DbGridColumn& _rColumn )
1030 :DbCellControl( _rColumn )
1032 doPropertyListening( FM_PROP_MAXTEXTLEN );
1036 void DbLimitedLengthField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1038 DBG_ASSERT( m_pWindow, "DbLimitedLengthField::implAdjustGenericFieldSetting: not to be called without window!" );
1039 DBG_ASSERT( _rxModel.is(), "DbLimitedLengthField::implAdjustGenericFieldSetting: invalid model!" );
1040 if ( m_pWindow && _rxModel.is() )
1042 sal_Int16 nMaxLen = 0;
1043 _rxModel->getPropertyValue( FM_PROP_MAXTEXTLEN ) >>= nMaxLen;
1044 implSetMaxTextLen( nMaxLen );
1048 void DbLimitedLengthField::implSetEffectiveMaxTextLen( sal_Int32 _nMaxLen )
1050 dynamic_cast<Edit&>(*m_pWindow).SetMaxTextLen(_nMaxLen);
1051 if (m_pPainter)
1052 dynamic_cast<Edit&>(*m_pPainter).SetMaxTextLen(_nMaxLen);
1055 DbTextField::DbTextField(DbGridColumn& _rColumn)
1056 :DbLimitedLengthField(_rColumn)
1057 ,m_pEdit( nullptr )
1058 ,m_pPainterImplementation( nullptr )
1059 ,m_bIsSimpleEdit( true )
1064 DbTextField::~DbTextField( )
1066 DELETEZ( m_pPainterImplementation );
1067 DELETEZ( m_pEdit );
1071 void DbTextField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
1073 sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1);
1075 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1077 WinBits nStyle = WB_LEFT;
1078 switch (nAlignment)
1080 case awt::TextAlign::RIGHT:
1081 nStyle = WB_RIGHT;
1082 break;
1084 case awt::TextAlign::CENTER:
1085 nStyle = WB_CENTER;
1086 break;
1089 // is this a multi-line field?
1090 bool bIsMultiLine = false;
1093 if ( xModel.is() )
1095 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MULTILINE ) >>= bIsMultiLine );
1098 catch( const Exception& )
1100 OSL_FAIL( "DbTextField::Init: caught an exception while determining the multi-line capabilities!" );
1101 DBG_UNHANDLED_EXCEPTION();
1104 m_bIsSimpleEdit = !bIsMultiLine;
1105 if ( bIsMultiLine )
1107 m_pWindow = VclPtr<MultiLineTextCell>::Create( &rParent, nStyle );
1108 m_pEdit = new MultiLineEditImplementation( *static_cast< MultiLineTextCell* >( m_pWindow.get() ) );
1110 m_pPainter = VclPtr<MultiLineTextCell>::Create( &rParent, nStyle );
1111 m_pPainterImplementation = new MultiLineEditImplementation( *static_cast< MultiLineTextCell* >( m_pPainter.get() ) );
1113 else
1115 m_pWindow = VclPtr<Edit>::Create( &rParent, nStyle );
1116 m_pEdit = new EditImplementation( *static_cast< Edit* >( m_pWindow.get() ) );
1118 m_pPainter = VclPtr<Edit>::Create( &rParent, nStyle );
1119 m_pPainterImplementation = new EditImplementation( *static_cast< Edit* >( m_pPainter.get() ) );
1122 if ( WB_LEFT == nStyle )
1124 // this is so that when getting the focus, the selection is oriented left-to-right
1125 AllSettings aSettings = m_pWindow->GetSettings();
1126 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1127 aStyleSettings.SetSelectionOptions(
1128 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
1129 aSettings.SetStyleSettings(aStyleSettings);
1130 m_pWindow->SetSettings(aSettings);
1133 implAdjustGenericFieldSetting( xModel );
1135 DbLimitedLengthField::Init( rParent, xCursor );
1139 CellControllerRef DbTextField::CreateController() const
1141 return new EditCellController( m_pEdit );
1145 void DbTextField::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1147 if ( m_pPainterImplementation )
1148 m_pPainterImplementation->SetText( GetFormatText( _rxField, _rxFormatter ) );
1150 DbLimitedLengthField::PaintFieldToCell( _rDev, _rRect, _rxField, _rxFormatter );
1154 OUString DbTextField::GetFormatText(const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, Color** /*ppColor*/)
1156 const css::uno::Reference<css::beans::XPropertySet> xPS(_rxField, UNO_QUERY);
1157 FormattedColumnValue fmter( xFormatter, xPS );
1159 return fmter.getFormattedValue();
1163 void DbTextField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
1165 m_pEdit->SetText( GetFormatText( _rxField, xFormatter ) );
1166 m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1170 void DbTextField::updateFromModel( Reference< XPropertySet > _rxModel )
1172 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTextField::updateFromModel: invalid call!" );
1174 OUString sText;
1175 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
1177 sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen();
1178 if ( EDIT_NOLIMIT != nMaxTextLen && sText.getLength() > nMaxTextLen )
1180 sal_Int32 nDiff = sText.getLength() - nMaxTextLen;
1181 sText = sText.replaceAt(sText.getLength() - nDiff,nDiff, OUString());
1185 m_pEdit->SetText( sText );
1186 m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1190 bool DbTextField::commitControl()
1192 OUString aText( m_pEdit->GetText( getModelLineEndSetting( m_rColumn.getModel() ) ) );
1193 // we have to check if the length before we can decide if the value was modified
1194 sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen();
1195 if ( EDIT_NOLIMIT != nMaxTextLen )
1197 OUString sOldValue;
1198 m_rColumn.getModel()->getPropertyValue( FM_PROP_TEXT ) >>= sOldValue;
1199 // if the new value didn't change we must set the old long value again
1200 if ( sOldValue.getLength() > nMaxTextLen && sOldValue.compareTo(aText,nMaxTextLen) == 0 )
1201 aText = sOldValue;
1203 m_rColumn.getModel()->setPropertyValue( FM_PROP_TEXT, makeAny( aText ) );
1204 return true;
1208 void DbTextField::implSetEffectiveMaxTextLen( sal_Int32 _nMaxLen )
1210 if ( m_pEdit )
1211 m_pEdit->SetMaxTextLen( _nMaxLen );
1212 if ( m_pPainterImplementation )
1213 m_pPainterImplementation->SetMaxTextLen( _nMaxLen );
1216 DbFormattedField::DbFormattedField(DbGridColumn& _rColumn)
1217 :DbLimitedLengthField(_rColumn)
1218 ,m_nKeyType(css::util::NumberFormat::UNDEFINED)
1221 // if our model's format key changes we want to propagate the new value to our windows
1222 doPropertyListening( FM_PROP_FORMATKEY );
1226 DbFormattedField::~DbFormattedField()
1231 void DbFormattedField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
1233 sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1);
1235 Reference< css::beans::XPropertySet > xUnoModel = m_rColumn.getModel();
1237 switch (nAlignment)
1239 case css::awt::TextAlign::RIGHT:
1240 m_pWindow = VclPtr<FormattedField>::Create( &rParent, WB_RIGHT );
1241 m_pPainter = VclPtr<FormattedField>::Create( &rParent, WB_RIGHT );
1242 break;
1244 case css::awt::TextAlign::CENTER:
1245 m_pWindow = VclPtr<FormattedField>::Create( &rParent, WB_CENTER );
1246 m_pPainter = VclPtr<FormattedField>::Create( &rParent, WB_CENTER );
1247 break;
1248 default:
1249 m_pWindow = VclPtr<FormattedField>::Create( &rParent, WB_LEFT );
1250 m_pPainter = VclPtr<FormattedField>::Create( &rParent, WB_LEFT );
1252 // Everything just so that the selection goes from right to left when getting focus
1253 AllSettings aSettings = m_pWindow->GetSettings();
1254 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1255 aStyleSettings.SetSelectionOptions(
1256 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
1257 aSettings.SetStyleSettings(aStyleSettings);
1258 m_pWindow->SetSettings(aSettings);
1261 implAdjustGenericFieldSetting( xUnoModel );
1263 static_cast< FormattedField* >( m_pWindow.get() )->SetStrictFormat( false );
1264 static_cast< FormattedField* >( m_pPainter.get() )->SetStrictFormat( false );
1265 // if one allows any formatting, one cannot make an entry check anyway
1266 // (the FormattedField does not support that anyway, only derived classes)
1268 // get the formatter from the uno model
1269 // (I could theoretically also go via the css::util::NumberFormatter, which the cursor would
1270 // surely give me. The problem is that I can not really rely on the fact that the two
1271 // formatters are the same. Clean is the whole thing if I go via the UNO model.)
1272 sal_Int32 nFormatKey = -1;
1274 // let's see if the model has one ...
1275 DBG_ASSERT(::comphelper::hasProperty(FM_PROP_FORMATSSUPPLIER, xUnoModel), "DbFormattedField::Init : invalid UNO model !");
1276 Any aSupplier( xUnoModel->getPropertyValue(FM_PROP_FORMATSSUPPLIER));
1277 if (aSupplier.hasValue())
1279 m_xSupplier.set(aSupplier, css::uno::UNO_QUERY);
1280 if (m_xSupplier.is())
1282 // if we take the supplier from the model, then also the key
1283 Any aFmtKey( xUnoModel->getPropertyValue(FM_PROP_FORMATKEY));
1284 if (aFmtKey.hasValue())
1286 DBG_ASSERT(aFmtKey.getValueType().getTypeClass() == TypeClass_LONG, "DbFormattedField::Init : invalid format key property (no sal_Int32) !");
1287 nFormatKey = ::comphelper::getINT32(aFmtKey);
1289 else
1291 SAL_INFO("svx.fmcomp", "DbFormattedField::Init : my uno-model has no format-key, but a formats supplier !");
1292 // the OFormattedModel which we usually are working with ensures that the model has a format key
1293 // as soon as the form is loaded. Unfortunally this method here is called from within loaded, too.
1294 // So if our LoadListener is called before the LoadListener of the model, this "else case" is
1295 // allowed.
1296 // Of course our property listener for the FormatKey property will notify us if the prop is changed,
1297 // so this here isn't really bad ....
1298 nFormatKey = 0;
1303 // No? Maybe the css::form::component::Form behind the cursor?
1304 if (!m_xSupplier.is())
1306 Reference< XRowSet > xCursorForm(xCursor, UNO_QUERY);
1307 if (xCursorForm.is())
1308 { // If we take the formatter from the cursor, then also the key from the field to which we are bound
1309 m_xSupplier = getNumberFormats(getConnection(xCursorForm));
1311 if (m_rColumn.GetField().is())
1312 nFormatKey = ::comphelper::getINT32(m_rColumn.GetField()->getPropertyValue(FM_PROP_FORMATKEY));
1316 SvNumberFormatter* pFormatterUsed = nullptr;
1317 if (m_xSupplier.is())
1319 SvNumberFormatsSupplierObj* pImplmentation = SvNumberFormatsSupplierObj::getImplementation(m_xSupplier);
1320 if (pImplmentation)
1321 pFormatterUsed = pImplmentation->GetNumberFormatter();
1322 else
1323 // Everything is invalid: the supplier is of the wrong type, then we can not
1324 // rely on a standard formatter to know the (possibly non-standard) key.
1325 nFormatKey = -1;
1328 // a standard formatter ...
1329 if (pFormatterUsed == nullptr)
1331 pFormatterUsed = static_cast<FormattedField*>(m_pWindow.get())->StandardFormatter();
1332 DBG_ASSERT(pFormatterUsed != nullptr, "DbFormattedField::Init : no standard formatter given by the numeric field !");
1334 // ... and a standard key
1335 if (nFormatKey == -1)
1336 nFormatKey = 0;
1338 m_nKeyType = comphelper::getNumberFormatType(m_xSupplier->getNumberFormats(), nFormatKey);
1340 static_cast<FormattedField*>(m_pWindow.get())->SetFormatter(pFormatterUsed);
1341 static_cast<FormattedField*>(m_pPainter.get())->SetFormatter(pFormatterUsed);
1343 static_cast<FormattedField*>(m_pWindow.get())->SetFormatKey(nFormatKey);
1344 static_cast<FormattedField*>(m_pPainter.get())->SetFormatKey(nFormatKey);
1346 static_cast<FormattedField*>(m_pWindow.get())->TreatAsNumber(m_rColumn.IsNumeric());
1347 static_cast<FormattedField*>(m_pPainter.get())->TreatAsNumber(m_rColumn.IsNumeric());
1349 // min and max values
1350 if (m_rColumn.IsNumeric())
1352 bool bClearMin = true;
1353 if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MIN, xUnoModel))
1355 Any aMin( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MIN));
1356 if (aMin.getValueType().getTypeClass() != TypeClass_VOID)
1358 DBG_ASSERT(aMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid min value !");
1359 double dMin = ::comphelper::getDouble(aMin);
1360 static_cast<FormattedField*>(m_pWindow.get())->SetMinValue(dMin);
1361 static_cast<FormattedField*>(m_pPainter.get())->SetMinValue(dMin);
1362 bClearMin = false;
1365 if (bClearMin)
1367 static_cast<FormattedField*>(m_pWindow.get())->ClearMinValue();
1368 static_cast<FormattedField*>(m_pPainter.get())->ClearMinValue();
1370 bool bClearMax = true;
1371 if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MAX, xUnoModel))
1373 Any aMin( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MAX));
1374 if (aMin.getValueType().getTypeClass() != TypeClass_VOID)
1376 DBG_ASSERT(aMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid max value !");
1377 double dMin = ::comphelper::getDouble(aMin);
1378 static_cast<FormattedField*>(m_pWindow.get())->SetMaxValue(dMin);
1379 static_cast<FormattedField*>(m_pPainter.get())->SetMaxValue(dMin);
1380 bClearMax = false;
1383 if (bClearMax)
1385 static_cast<FormattedField*>(m_pWindow.get())->ClearMaxValue();
1386 static_cast<FormattedField*>(m_pPainter.get())->ClearMaxValue();
1390 // the default value
1391 Any aDefault( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_DEFAULT));
1392 if (aDefault.hasValue())
1393 { // the thing can be a double or a string
1394 switch (aDefault.getValueType().getTypeClass())
1396 case TypeClass_DOUBLE:
1397 if (m_rColumn.IsNumeric())
1399 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultValue(::comphelper::getDouble(aDefault));
1400 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultValue(::comphelper::getDouble(aDefault));
1402 else
1404 OUString sConverted;
1405 Color* pDummy;
1406 pFormatterUsed->GetOutputString(::comphelper::getDouble(aDefault), 0, sConverted, &pDummy);
1407 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultText(sConverted);
1408 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultText(sConverted);
1410 break;
1411 case TypeClass_STRING:
1413 OUString sDefault( ::comphelper::getString(aDefault) );
1414 if (m_rColumn.IsNumeric())
1416 double dVal;
1417 sal_uInt32 nTestFormat(0);
1418 if (pFormatterUsed->IsNumberFormat(sDefault, nTestFormat, dVal))
1420 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultValue(dVal);
1421 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultValue(dVal);
1424 else
1426 static_cast<FormattedField*>(m_pWindow.get())->SetDefaultText(sDefault);
1427 static_cast<FormattedField*>(m_pPainter.get())->SetDefaultText(sDefault);
1430 break;
1431 default:
1432 OSL_FAIL( "DbFormattedField::Init: unexpected value type!" );
1433 break;
1436 DbLimitedLengthField::Init( rParent, xCursor );
1440 CellControllerRef DbFormattedField::CreateController() const
1442 return new ::svt::FormattedFieldCellController( static_cast< FormattedField* >( m_pWindow.get() ) );
1446 void DbFormattedField::_propertyChanged( const PropertyChangeEvent& _rEvent )
1448 if (_rEvent.PropertyName == FM_PROP_FORMATKEY )
1450 sal_Int32 nNewKey = _rEvent.NewValue.hasValue() ? ::comphelper::getINT32(_rEvent.NewValue) : 0;
1451 m_nKeyType = comphelper::getNumberFormatType(m_xSupplier->getNumberFormats(), nNewKey);
1453 DBG_ASSERT(m_pWindow && m_pPainter, "DbFormattedField::_propertyChanged : where are my windows ?");
1454 if (m_pWindow)
1455 static_cast< FormattedField* >( m_pWindow.get() )->SetFormatKey( nNewKey );
1456 if (m_pPainter)
1457 static_cast< FormattedField* >( m_pPainter.get() )->SetFormatKey( nNewKey );
1459 else
1461 DbLimitedLengthField::_propertyChanged( _rEvent );
1466 OUString DbFormattedField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, Color** ppColor)
1468 // no color specification by default
1469 if (ppColor != nullptr)
1470 *ppColor = nullptr;
1472 // NULL value -> empty text
1473 if (!_rxField.is())
1474 return OUString();
1476 OUString aText;
1479 if (m_rColumn.IsNumeric())
1481 // The IsNumeric at the column says nothing about the class of the used format, but
1482 // about the class of the field bound to the column. So when you bind a FormattedField
1483 // column to a double field and format it as text, m_rColumn.IsNumeric() returns
1484 // sal_True. So that simply means that I can query the contents of the variant using
1485 // getDouble, and then I can leave the rest (the formatting) to the FormattedField.
1486 double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() );
1487 if (_rxField->wasNull())
1488 return aText;
1489 static_cast<FormattedField*>(m_pPainter.get())->SetValue(dValue);
1491 else
1493 // Here I can not work with a double, since the field can not provide it to me.
1494 // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form.
1495 aText = _rxField->getString();
1496 if (_rxField->wasNull())
1497 return aText;
1498 static_cast<FormattedField*>(m_pPainter.get())->SetTextFormatted(aText);
1501 catch( const Exception& )
1503 DBG_UNHANDLED_EXCEPTION();
1506 aText = m_pPainter->GetText();
1507 if (ppColor != nullptr)
1508 *ppColor = static_cast<FormattedField*>(m_pPainter.get())->GetLastOutputColor();
1510 return aText;
1514 void DbFormattedField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
1518 FormattedField* pFormattedWindow = static_cast<FormattedField*>(m_pWindow.get());
1519 if (!_rxField.is())
1520 { // NULL value -> empty text
1521 m_pWindow->SetText(OUString());
1523 else if (m_rColumn.IsNumeric())
1525 // The IsNumeric at the column says nothing about the class of the used format, but
1526 // about the class of the field bound to the column. So when you bind a FormattedField
1527 // column to a double field and format it as text, m_rColumn.IsNumeric() returns
1528 // sal_True. So that simply means that I can query the contents of the variant using
1529 // getDouble, and then I can leave the rest (the formatting) to the FormattedField.
1530 double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() );
1531 if (_rxField->wasNull())
1532 m_pWindow->SetText(OUString());
1533 else
1534 pFormattedWindow->SetValue(dValue);
1536 else
1538 // Here I can not work with a double, since the field can not provide it to me.
1539 // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form.
1540 OUString sText( _rxField->getString());
1542 pFormattedWindow->SetTextFormatted( sText );
1543 pFormattedWindow->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1546 catch( const Exception& )
1548 DBG_UNHANDLED_EXCEPTION();
1553 void DbFormattedField::updateFromModel( Reference< XPropertySet > _rxModel )
1555 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFormattedField::updateFromModel: invalid call!" );
1557 FormattedField* pFormattedWindow = static_cast< FormattedField* >( m_pWindow.get() );
1559 OUString sText;
1560 Any aValue = _rxModel->getPropertyValue( FM_PROP_EFFECTIVE_VALUE );
1561 if ( !aValue.hasValue() || (aValue >>= sText) )
1562 { // our effective value is transferred as string
1563 pFormattedWindow->SetTextFormatted( sText );
1564 pFormattedWindow->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1566 else
1568 double dValue = 0;
1569 aValue >>= dValue;
1570 pFormattedWindow->SetValue(dValue);
1575 bool DbFormattedField::commitControl()
1577 Any aNewVal;
1578 FormattedField& rField = *static_cast<FormattedField*>(m_pWindow.get());
1579 DBG_ASSERT(&rField == m_pWindow, "DbFormattedField::commitControl : can't work with a window other than my own !");
1580 if (m_rColumn.IsNumeric())
1582 if (!rField.GetText().isEmpty())
1583 aNewVal <<= rField.GetValue();
1584 // an empty string is passed on as void by default, to start with
1586 else
1587 aNewVal <<= rField.GetTextValue();
1589 m_rColumn.getModel()->setPropertyValue(FM_PROP_EFFECTIVE_VALUE, aNewVal);
1590 return true;
1593 DbCheckBox::DbCheckBox( DbGridColumn& _rColumn )
1594 :DbCellControl( _rColumn )
1596 setAlignedController( false );
1599 namespace
1601 void setCheckBoxStyle( vcl::Window* _pWindow, bool bMono )
1603 AllSettings aSettings = _pWindow->GetSettings();
1604 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1605 if( bMono )
1606 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::Mono );
1607 else
1608 aStyleSettings.SetOptions( aStyleSettings.GetOptions() & (~StyleSettingsOptions::Mono) );
1609 aSettings.SetStyleSettings( aStyleSettings );
1610 _pWindow->SetSettings( aSettings );
1615 void DbCheckBox::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor )
1617 setTransparent( true );
1619 m_pWindow = VclPtr<CheckBoxControl>::Create( &rParent );
1620 m_pPainter = VclPtr<CheckBoxControl>::Create( &rParent );
1622 m_pWindow->SetPaintTransparent( true );
1623 m_pPainter->SetPaintTransparent( true );
1625 m_pPainter->SetBackground();
1629 Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW );
1631 sal_Int16 nStyle = awt::VisualEffect::LOOK3D;
1632 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_VISUALEFFECT ) >>= nStyle );
1634 setCheckBoxStyle( m_pWindow, nStyle == awt::VisualEffect::FLAT );
1635 setCheckBoxStyle( m_pPainter, nStyle == awt::VisualEffect::FLAT );
1637 bool bTristate = true;
1638 OSL_VERIFY( xModel->getPropertyValue( FM_PROP_TRISTATE ) >>= bTristate );
1639 static_cast< CheckBoxControl* >( m_pWindow.get() )->GetBox().EnableTriState( bTristate );
1640 static_cast< CheckBoxControl* >( m_pPainter.get() )->GetBox().EnableTriState( bTristate );
1642 catch( const Exception& )
1644 DBG_UNHANDLED_EXCEPTION();
1647 DbCellControl::Init( rParent, xCursor );
1651 CellControllerRef DbCheckBox::CreateController() const
1653 return new CheckBoxCellController(static_cast<CheckBoxControl*>(m_pWindow.get()));
1656 static void lcl_setCheckBoxState( const Reference< css::sdb::XColumn >& _rxField,
1657 CheckBoxControl* _pCheckBoxControl )
1659 TriState eState = TRISTATE_INDET;
1660 if (_rxField.is())
1664 bool bValue = _rxField->getBoolean();
1665 if (!_rxField->wasNull())
1666 eState = bValue ? TRISTATE_TRUE : TRISTATE_FALSE;
1668 catch( const Exception& )
1670 DBG_UNHANDLED_EXCEPTION();
1673 _pCheckBoxControl->GetBox().SetState(eState);
1677 void DbCheckBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
1679 lcl_setCheckBoxState( _rxField, static_cast<CheckBoxControl*>(m_pWindow.get()) );
1683 void DbCheckBox::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect,
1684 const Reference< css::sdb::XColumn >& _rxField,
1685 const Reference< XNumberFormatter >& xFormatter)
1687 lcl_setCheckBoxState( _rxField, static_cast<CheckBoxControl*>(m_pPainter.get()) );
1688 DbCellControl::PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
1692 void DbCheckBox::updateFromModel( Reference< XPropertySet > _rxModel )
1694 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCheckBox::updateFromModel: invalid call!" );
1696 sal_Int16 nState = TRISTATE_INDET;
1697 _rxModel->getPropertyValue( FM_PROP_STATE ) >>= nState;
1698 static_cast< CheckBoxControl* >( m_pWindow.get() )->GetBox().SetState( static_cast< TriState >( nState ) );
1702 bool DbCheckBox::commitControl()
1704 m_rColumn.getModel()->setPropertyValue( FM_PROP_STATE,
1705 makeAny( (sal_Int16)( static_cast< CheckBoxControl* >( m_pWindow.get() )->GetBox().GetState() ) ) );
1706 return true;
1710 OUString DbCheckBox::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
1712 return OUString();
1715 DbPatternField::DbPatternField( DbGridColumn& _rColumn, const Reference<XComponentContext>& _rContext )
1716 :DbCellControl( _rColumn )
1717 ,m_xContext( _rContext )
1719 doPropertyListening( FM_PROP_LITERALMASK );
1720 doPropertyListening( FM_PROP_EDITMASK );
1721 doPropertyListening( FM_PROP_STRICTFORMAT );
1725 void DbPatternField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1727 DBG_ASSERT( m_pWindow, "DbPatternField::implAdjustGenericFieldSetting: not to be called without window!" );
1728 DBG_ASSERT( _rxModel.is(), "DbPatternField::implAdjustGenericFieldSetting: invalid model!" );
1729 if ( m_pWindow && _rxModel.is() )
1731 OUString aLitMask;
1732 OUString aEditMask;
1733 bool bStrict = false;
1735 _rxModel->getPropertyValue( FM_PROP_LITERALMASK ) >>= aLitMask;
1736 _rxModel->getPropertyValue( FM_PROP_EDITMASK ) >>= aEditMask;
1737 _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) >>= bStrict;
1739 OString aAsciiEditMask(OUStringToOString(aEditMask, RTL_TEXTENCODING_ASCII_US));
1741 static_cast< PatternField* >( m_pWindow.get() )->SetMask( aAsciiEditMask, aLitMask );
1742 static_cast< PatternField* >( m_pPainter.get() )->SetMask( aAsciiEditMask, aLitMask );
1743 static_cast< PatternField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
1744 static_cast< PatternField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
1749 void DbPatternField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
1751 m_rColumn.SetAlignmentFromModel(-1);
1753 m_pWindow = VclPtr<PatternField>::Create( &rParent, 0 );
1754 m_pPainter= VclPtr<PatternField>::Create( &rParent, 0 );
1756 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1757 implAdjustGenericFieldSetting( xModel );
1759 DbCellControl::Init( rParent, xCursor );
1763 CellControllerRef DbPatternField::CreateController() const
1765 return new SpinCellController( static_cast< PatternField* >( m_pWindow.get() ) );
1769 OUString DbPatternField::impl_formatText( const OUString& _rText )
1771 m_pPainter->SetText( _rText );
1772 static_cast< PatternField* >( m_pPainter.get() )->ReformatAll();
1773 return m_pPainter->GetText();
1777 OUString DbPatternField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
1779 bool bIsForPaint = _rxField != m_rColumn.GetField();
1780 ::std::unique_ptr< FormattedColumnValue >& rpFormatter = bIsForPaint ? m_pPaintFormatter : m_pValueFormatter;
1782 if ( !rpFormatter.get() )
1784 rpFormatter = o3tl::make_unique< FormattedColumnValue> (
1785 m_xContext, getCursor(), Reference< XPropertySet >( _rxField, UNO_QUERY ) );
1786 OSL_ENSURE( rpFormatter.get(), "DbPatternField::Init: no value formatter!" );
1788 else
1789 OSL_ENSURE( rpFormatter->getColumn() == _rxField, "DbPatternField::GetFormatText: my value formatter is working for another field ...!" );
1790 // re-creating the value formatter here every time would be quite expensive ...
1792 OUString sText;
1793 if ( rpFormatter.get() )
1794 sText = rpFormatter->getFormattedValue();
1796 return impl_formatText( sText );
1800 void DbPatternField::UpdateFromField( const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1802 static_cast< Edit* >( m_pWindow.get() )->SetText( GetFormatText( _rxField, _rxFormatter ) );
1803 static_cast< Edit* >( m_pWindow.get() )->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1807 void DbPatternField::updateFromModel( Reference< XPropertySet > _rxModel )
1809 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbPatternField::updateFromModel: invalid call!" );
1811 OUString sText;
1812 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
1814 static_cast< Edit* >( m_pWindow.get() )->SetText( impl_formatText( sText ) );
1815 static_cast< Edit* >( m_pWindow.get() )->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
1819 bool DbPatternField::commitControl()
1821 OUString aText(m_pWindow->GetText());
1822 m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, makeAny(aText));
1823 return true;
1826 DbSpinField::DbSpinField( DbGridColumn& _rColumn, sal_Int16 _nStandardAlign )
1827 :DbCellControl( _rColumn )
1828 ,m_nStandardAlign( _nStandardAlign )
1833 void DbSpinField::Init( vcl::Window& _rParent, const Reference< XRowSet >& _rxCursor )
1835 m_rColumn.SetAlignmentFromModel( m_nStandardAlign );
1837 Reference< XPropertySet > xModel( m_rColumn.getModel() );
1839 // determine the WinBits for the field
1840 WinBits nFieldStyle = 0;
1841 if ( ::comphelper::getBOOL( xModel->getPropertyValue( FM_PROP_SPIN ) ) )
1842 nFieldStyle = WB_REPEAT | WB_SPIN;
1843 // create the fields
1844 m_pWindow = createField( &_rParent, nFieldStyle, xModel );
1845 m_pPainter = createField( &_rParent, nFieldStyle, xModel );
1847 // adjust all other settings which depend on the property values
1848 implAdjustGenericFieldSetting( xModel );
1850 // call the base class
1851 DbCellControl::Init( _rParent, _rxCursor );
1855 CellControllerRef DbSpinField::CreateController() const
1857 return new SpinCellController( static_cast< SpinField* >( m_pWindow.get() ) );
1860 DbNumericField::DbNumericField( DbGridColumn& _rColumn )
1861 :DbSpinField( _rColumn )
1863 doPropertyListening( FM_PROP_DECIMAL_ACCURACY );
1864 doPropertyListening( FM_PROP_VALUEMIN );
1865 doPropertyListening( FM_PROP_VALUEMAX );
1866 doPropertyListening( FM_PROP_VALUESTEP );
1867 doPropertyListening( FM_PROP_STRICTFORMAT );
1868 doPropertyListening( FM_PROP_SHOWTHOUSANDSEP );
1872 void DbNumericField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
1874 DBG_ASSERT( m_pWindow, "DbNumericField::implAdjustGenericFieldSetting: not to be called without window!" );
1875 DBG_ASSERT( _rxModel.is(), "DbNumericField::implAdjustGenericFieldSetting: invalid model!" );
1876 if ( m_pWindow && _rxModel.is() )
1878 sal_Int32 nMin = (sal_Int32)getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) );
1879 sal_Int32 nMax = (sal_Int32)getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) );
1880 sal_Int32 nStep = (sal_Int32)getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) );
1881 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
1882 sal_Int16 nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) );
1883 bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) );
1885 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetMinValue(nMin);
1886 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetMaxValue(nMax);
1887 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetSpinSize(nStep);
1888 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetStrictFormat(bStrict);
1890 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetMinValue(nMin);
1891 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetMaxValue(nMax);
1892 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetStrictFormat(bStrict);
1895 // give a formatter to the field and the painter;
1896 // test first if I can get from the service behind a connection
1897 Reference< css::util::XNumberFormatsSupplier > xSupplier;
1898 Reference< XRowSet > xForm;
1899 if ( m_rColumn.GetParent().getDataSource() )
1900 xForm.set( Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY );
1901 if ( xForm.is() )
1902 xSupplier = getNumberFormats( getConnection( xForm ), true );
1903 SvNumberFormatter* pFormatterUsed = nullptr;
1904 if ( xSupplier.is() )
1906 SvNumberFormatsSupplierObj* pImplmentation = SvNumberFormatsSupplierObj::getImplementation( xSupplier );
1907 pFormatterUsed = pImplmentation ? pImplmentation->GetNumberFormatter() : nullptr;
1909 if ( nullptr == pFormatterUsed )
1910 { // the cursor didn't lead to success -> standard
1911 pFormatterUsed = static_cast< DoubleNumericField* >( m_pWindow.get() )->StandardFormatter();
1912 DBG_ASSERT( pFormatterUsed != nullptr, "DbNumericField::implAdjustGenericFieldSetting: no standard formatter given by the numeric field !" );
1914 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetFormatter( pFormatterUsed );
1915 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetFormatter( pFormatterUsed );
1917 // and then generate a format which has the desired length after the decimal point, etc.
1918 LanguageType aAppLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType();
1919 OUString sFormatString = pFormatterUsed->GenerateFormat(0, aAppLanguage, bThousand, false, nScale);
1921 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetFormat( sFormatString, aAppLanguage );
1922 static_cast< DoubleNumericField* >( m_pPainter.get() )->SetFormat( sFormatString, aAppLanguage );
1927 VclPtr<SpinField> DbNumericField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& /*_rxModel*/ )
1929 return VclPtr<DoubleNumericField>::Create( _pParent, _nFieldStyle );
1932 namespace
1935 OUString lcl_setFormattedNumeric_nothrow( DoubleNumericField& _rField, const DbCellControl& _rControl,
1936 const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
1938 OUString sValue;
1939 if ( _rxField.is() )
1943 double fValue = _rControl.GetValue( _rxField, _rxFormatter );
1944 if ( !_rxField->wasNull() )
1946 _rField.SetValue( fValue );
1947 sValue = _rField.GetText();
1950 catch( const Exception& )
1952 DBG_UNHANDLED_EXCEPTION();
1955 return sValue;
1960 OUString DbNumericField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, Color** /*ppColor*/)
1962 return lcl_setFormattedNumeric_nothrow(dynamic_cast<DoubleNumericField&>(*m_pPainter), *this, _rxField, _rxFormatter);
1966 void DbNumericField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter)
1968 lcl_setFormattedNumeric_nothrow(dynamic_cast<DoubleNumericField&>(*m_pWindow), *this, _rxField, _rxFormatter);
1972 void DbNumericField::updateFromModel( Reference< XPropertySet > _rxModel )
1974 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbNumericField::updateFromModel: invalid call!" );
1976 double dValue = 0;
1977 if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue )
1978 static_cast< DoubleNumericField* >( m_pWindow.get() )->SetValue( dValue );
1979 else
1980 m_pWindow->SetText( OUString() );
1984 bool DbNumericField::commitControl()
1986 OUString aText( m_pWindow->GetText());
1987 Any aVal;
1989 if (!aText.isEmpty()) // not empty
1991 double fValue = static_cast<DoubleNumericField*>(m_pWindow.get())->GetValue();
1992 aVal <<= fValue;
1994 m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal);
1995 return true;
1998 DbCurrencyField::DbCurrencyField(DbGridColumn& _rColumn)
1999 :DbSpinField( _rColumn )
2000 ,m_nScale( 0 )
2002 doPropertyListening( FM_PROP_DECIMAL_ACCURACY );
2003 doPropertyListening( FM_PROP_VALUEMIN );
2004 doPropertyListening( FM_PROP_VALUEMAX );
2005 doPropertyListening( FM_PROP_VALUESTEP );
2006 doPropertyListening( FM_PROP_STRICTFORMAT );
2007 doPropertyListening( FM_PROP_SHOWTHOUSANDSEP );
2008 doPropertyListening( FM_PROP_CURRENCYSYMBOL );
2012 void DbCurrencyField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2014 DBG_ASSERT( m_pWindow, "DbCurrencyField::implAdjustGenericFieldSetting: not to be called without window!" );
2015 DBG_ASSERT( _rxModel.is(), "DbCurrencyField::implAdjustGenericFieldSetting: invalid model!" );
2016 if ( m_pWindow && _rxModel.is() )
2018 m_nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) );
2019 double nMin = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) );
2020 double nMax = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) );
2021 double nStep = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) );
2022 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2023 bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) );
2024 OUString aStr( getString( _rxModel->getPropertyValue(FM_PROP_CURRENCYSYMBOL ) ) );
2026 //fdo#42747 the min/max/first/last of vcl NumericFormatters needs to be
2027 //multiplied by the no of decimal places. See also
2028 //VclBuilder::mungeAdjustment
2029 int nMul = rtl_math_pow10Exp(1, m_nScale);
2030 nMin *= nMul;
2031 nMax *= nMul;
2033 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetUseThousandSep( bThousand );
2034 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetDecimalDigits( m_nScale );
2035 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetCurrencySymbol( aStr );
2036 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetFirst( nMin );
2037 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetLast( nMax );
2038 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetMin( nMin );
2039 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetMax( nMax );
2040 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetSpinSize( nStep );
2041 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
2043 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetUseThousandSep( bThousand );
2044 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetDecimalDigits( m_nScale );
2045 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetCurrencySymbol( aStr );
2046 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetFirst( nMin );
2047 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetLast( nMax );
2048 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetMin( nMin );
2049 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetMax( nMax );
2050 static_cast< LongCurrencyField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
2055 VclPtr<SpinField> DbCurrencyField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& /*_rxModel*/ )
2057 return VclPtr<LongCurrencyField>::Create( _pParent, _nFieldStyle );
2061 double DbCurrencyField::GetCurrency(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) const
2063 double fValue = GetValue(_rxField, xFormatter);
2064 if (m_nScale)
2066 // SAL_INFO("svx",("double = %.64f ",fValue);
2067 fValue = ::rtl::math::pow10Exp(fValue, m_nScale);
2068 fValue = ::rtl::math::round(fValue);
2070 return fValue;
2073 namespace
2076 OUString lcl_setFormattedCurrency_nothrow( LongCurrencyField& _rField, const DbCurrencyField& _rControl,
2077 const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter )
2079 OUString sValue;
2080 if ( _rxField.is() )
2084 double fValue = _rControl.GetCurrency( _rxField, _rxFormatter );
2085 if ( !_rxField->wasNull() )
2087 _rField.SetValue( fValue );
2088 sValue = _rField.GetText();
2091 catch( const Exception& )
2093 DBG_UNHANDLED_EXCEPTION();
2096 return sValue;
2101 OUString DbCurrencyField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, Color** /*ppColor*/)
2103 return lcl_setFormattedCurrency_nothrow( dynamic_cast< LongCurrencyField& >( *m_pPainter ), *this, _rxField, _rxFormatter );
2107 void DbCurrencyField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter)
2109 lcl_setFormattedCurrency_nothrow( dynamic_cast< LongCurrencyField& >( *m_pWindow ), *this, _rxField, _rxFormatter );
2113 void DbCurrencyField::updateFromModel( Reference< XPropertySet > _rxModel )
2115 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCurrencyField::updateFromModel: invalid call!" );
2117 double dValue = 0;
2118 if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue )
2120 if ( m_nScale )
2122 dValue = ::rtl::math::pow10Exp( dValue, m_nScale );
2123 dValue = ::rtl::math::round(dValue);
2126 static_cast< LongCurrencyField* >( m_pWindow.get() )->SetValue( dValue );
2128 else
2129 m_pWindow->SetText( OUString() );
2133 bool DbCurrencyField::commitControl()
2135 OUString aText(m_pWindow->GetText());
2136 Any aVal;
2137 if (!aText.isEmpty()) // not empty
2139 double fValue = static_cast<LongCurrencyField*>(m_pWindow.get())->GetValue();
2140 if (m_nScale)
2142 fValue /= ::rtl::math::pow10Exp(1.0, m_nScale);
2144 aVal <<= fValue;
2146 m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal);
2147 return true;
2150 DbDateField::DbDateField( DbGridColumn& _rColumn )
2151 :DbSpinField( _rColumn )
2153 doPropertyListening( FM_PROP_DATEFORMAT );
2154 doPropertyListening( FM_PROP_DATEMIN );
2155 doPropertyListening( FM_PROP_DATEMAX );
2156 doPropertyListening( FM_PROP_STRICTFORMAT );
2157 doPropertyListening( FM_PROP_DATE_SHOW_CENTURY );
2161 VclPtr<SpinField> DbDateField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& _rxModel )
2163 // check if there is a DropDown property set to TRUE
2164 bool bDropDown = !hasProperty( FM_PROP_DROPDOWN, _rxModel )
2165 || getBOOL( _rxModel->getPropertyValue( FM_PROP_DROPDOWN ) );
2166 if ( bDropDown )
2167 _nFieldStyle |= WB_DROPDOWN;
2169 VclPtr<CalendarField> pField = VclPtr<CalendarField>::Create( _pParent, _nFieldStyle );
2171 pField->EnableToday();
2172 pField->EnableNone();
2174 return pField;
2178 void DbDateField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2180 DBG_ASSERT( m_pWindow, "DbDateField::implAdjustGenericFieldSetting: not to be called without window!" );
2181 DBG_ASSERT( _rxModel.is(), "DbDateField::implAdjustGenericFieldSetting: invalid model!" );
2182 if ( m_pWindow && _rxModel.is() )
2184 sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_DATEFORMAT ) );
2185 util::Date aMin;
2186 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMIN ) >>= aMin );
2187 util::Date aMax;
2188 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMAX ) >>= aMax );
2189 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2191 Any aCentury = _rxModel->getPropertyValue( FM_PROP_DATE_SHOW_CENTURY );
2192 if ( aCentury.getValueType().getTypeClass() != TypeClass_VOID )
2194 bool bShowDateCentury = getBOOL( aCentury );
2196 static_cast<DateField*>( m_pWindow.get() )->SetShowDateCentury( bShowDateCentury );
2197 static_cast<DateField*>( m_pPainter.get() )->SetShowDateCentury( bShowDateCentury );
2200 static_cast< DateField* >( m_pWindow.get() )->SetExtDateFormat( (ExtDateFieldFormat)nFormat );
2201 static_cast< DateField* >( m_pWindow.get() )->SetMin( aMin );
2202 static_cast< DateField* >( m_pWindow.get() )->SetMax( aMax );
2203 static_cast< DateField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
2204 static_cast< DateField* >( m_pWindow.get() )->EnableEmptyFieldValue( true );
2206 static_cast< DateField* >( m_pPainter.get() )->SetExtDateFormat( (ExtDateFieldFormat)nFormat );
2207 static_cast< DateField* >( m_pPainter.get() )->SetMin( aMin );
2208 static_cast< DateField* >( m_pPainter.get() )->SetMax( aMax );
2209 static_cast< DateField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
2210 static_cast< DateField* >( m_pPainter.get() )->EnableEmptyFieldValue( true );
2214 namespace
2217 OUString lcl_setFormattedDate_nothrow( DateField& _rField, const Reference< XColumn >& _rxField )
2219 OUString sDate;
2220 if ( _rxField.is() )
2224 css::util::Date aValue = _rxField->getDate();
2225 if ( _rxField->wasNull() )
2226 _rField.SetText( sDate );
2227 else
2229 _rField.SetDate( ::Date( aValue.Day, aValue.Month, aValue.Year ) );
2230 sDate = _rField.GetText();
2233 catch( const Exception& )
2235 DBG_UNHANDLED_EXCEPTION();
2238 return sDate;
2242 OUString DbDateField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
2244 return lcl_setFormattedDate_nothrow(dynamic_cast<DateField&>(*m_pPainter.get()), _rxField);
2248 void DbDateField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
2250 lcl_setFormattedDate_nothrow(dynamic_cast<DateField&>(*m_pWindow.get()), _rxField);
2254 void DbDateField::updateFromModel( Reference< XPropertySet > _rxModel )
2256 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbDateField::updateFromModel: invalid call!" );
2258 util::Date aDate;
2259 if ( _rxModel->getPropertyValue( FM_PROP_DATE ) >>= aDate )
2260 static_cast< DateField* >( m_pWindow.get() )->SetDate( ::Date( aDate ) );
2261 else
2262 static_cast< DateField* >( m_pWindow.get() )->SetText( OUString() );
2266 bool DbDateField::commitControl()
2268 OUString aText(m_pWindow->GetText());
2269 Any aVal;
2270 if (!aText.isEmpty())
2271 aVal <<= static_cast<DateField*>(m_pWindow.get())->GetDate().GetUNODate();
2272 else
2273 aVal.clear();
2275 m_rColumn.getModel()->setPropertyValue(FM_PROP_DATE, aVal);
2276 return true;
2279 DbTimeField::DbTimeField( DbGridColumn& _rColumn )
2280 :DbSpinField( _rColumn, css::awt::TextAlign::LEFT )
2282 doPropertyListening( FM_PROP_TIMEFORMAT );
2283 doPropertyListening( FM_PROP_TIMEMIN );
2284 doPropertyListening( FM_PROP_TIMEMAX );
2285 doPropertyListening( FM_PROP_STRICTFORMAT );
2289 VclPtr<SpinField> DbTimeField::createField( vcl::Window* _pParent, WinBits _nFieldStyle, const Reference< XPropertySet >& /*_rxModel*/ )
2291 return VclPtr<TimeField>::Create( _pParent, _nFieldStyle );
2295 void DbTimeField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2297 DBG_ASSERT( m_pWindow, "DbTimeField::implAdjustGenericFieldSetting: not to be called without window!" );
2298 DBG_ASSERT( _rxModel.is(), "DbTimeField::implAdjustGenericFieldSetting: invalid model!" );
2299 if ( m_pWindow && _rxModel.is() )
2301 sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_TIMEFORMAT ) );
2302 util::Time aMin;
2303 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMIN ) >>= aMin );
2304 util::Time aMax;
2305 OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMAX ) >>= aMax );
2306 bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) );
2308 static_cast< TimeField* >( m_pWindow.get() )->SetExtFormat( (ExtTimeFieldFormat)nFormat );
2309 static_cast< TimeField* >( m_pWindow.get() )->SetMin( aMin );
2310 static_cast< TimeField* >( m_pWindow.get() )->SetMax( aMax );
2311 static_cast< TimeField* >( m_pWindow.get() )->SetStrictFormat( bStrict );
2312 static_cast< TimeField* >( m_pWindow.get() )->EnableEmptyFieldValue( true );
2314 static_cast< TimeField* >( m_pPainter.get() )->SetExtFormat( (ExtTimeFieldFormat)nFormat );
2315 static_cast< TimeField* >( m_pPainter.get() )->SetMin( aMin );
2316 static_cast< TimeField* >( m_pPainter.get() )->SetMax( aMax );
2317 static_cast< TimeField* >( m_pPainter.get() )->SetStrictFormat( bStrict );
2318 static_cast< TimeField* >( m_pPainter.get() )->EnableEmptyFieldValue( true );
2322 namespace
2325 OUString lcl_setFormattedTime_nothrow( TimeField& _rField, const Reference< XColumn >& _rxField )
2327 OUString sTime;
2328 if ( _rxField.is() )
2332 css::util::Time aValue = _rxField->getTime();
2333 if ( _rxField->wasNull() )
2334 _rField.SetText( sTime );
2335 else
2337 _rField.SetTime( ::tools::Time( aValue ) );
2338 sTime = _rField.GetText();
2341 catch( const Exception& )
2343 DBG_UNHANDLED_EXCEPTION();
2346 return sTime;
2350 OUString DbTimeField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
2352 return lcl_setFormattedTime_nothrow( *static_cast< TimeField* >( m_pPainter.get() ), _rxField );
2356 void DbTimeField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/)
2358 lcl_setFormattedTime_nothrow( *static_cast< TimeField* >( m_pWindow.get() ), _rxField );
2362 void DbTimeField::updateFromModel( Reference< XPropertySet > _rxModel )
2364 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTimeField::updateFromModel: invalid call!" );
2366 util::Time aTime;
2367 if ( _rxModel->getPropertyValue( FM_PROP_TIME ) >>= aTime )
2368 static_cast< TimeField* >( m_pWindow.get() )->SetTime( ::tools::Time( aTime ) );
2369 else
2370 static_cast< TimeField* >( m_pWindow.get() )->SetText( OUString() );
2374 bool DbTimeField::commitControl()
2376 OUString aText(m_pWindow->GetText());
2377 Any aVal;
2378 if (!aText.isEmpty())
2379 aVal <<= static_cast<TimeField*>(m_pWindow.get())->GetTime().GetUNOTime();
2380 else
2381 aVal.clear();
2383 m_rColumn.getModel()->setPropertyValue(FM_PROP_TIME, aVal);
2384 return true;
2387 DbComboBox::DbComboBox(DbGridColumn& _rColumn)
2388 :DbCellControl(_rColumn)
2390 setAlignedController( false );
2392 doPropertyListening( FM_PROP_STRINGITEMLIST );
2393 doPropertyListening( FM_PROP_LINECOUNT );
2397 void DbComboBox::_propertyChanged( const PropertyChangeEvent& _rEvent )
2399 if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST )
2401 SetList(_rEvent.NewValue);
2403 else
2405 DbCellControl::_propertyChanged( _rEvent ) ;
2410 void DbComboBox::SetList(const Any& rItems)
2412 ComboBoxControl* pField = static_cast<ComboBoxControl*>(m_pWindow.get());
2413 pField->Clear();
2415 css::uno::Sequence<OUString> aTest;
2416 if (rItems >>= aTest)
2418 const OUString* pStrings = aTest.getConstArray();
2419 sal_Int32 nItems = aTest.getLength();
2420 for (sal_Int32 i = 0; i < nItems; ++i, ++pStrings )
2421 pField->InsertEntry(*pStrings);
2423 // tell the grid control that this controller is invalid and has to be re-initialized
2424 invalidatedController();
2429 void DbComboBox::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2431 DBG_ASSERT( m_pWindow, "DbComboBox::implAdjustGenericFieldSetting: not to be called without window!" );
2432 DBG_ASSERT( _rxModel.is(), "DbComboBox::implAdjustGenericFieldSetting: invalid model!" );
2433 if ( m_pWindow && _rxModel.is() )
2435 sal_Int16 nLines = getINT16( _rxModel->getPropertyValue( FM_PROP_LINECOUNT ) );
2436 static_cast< ComboBoxControl* >( m_pWindow.get() )->SetDropDownLineCount( nLines );
2441 void DbComboBox::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor )
2443 m_rColumn.SetAlignmentFromModel(css::awt::TextAlign::LEFT);
2445 m_pWindow = VclPtr<ComboBoxControl>::Create( &rParent );
2447 // selection from right to left
2448 AllSettings aSettings = m_pWindow->GetSettings();
2449 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2450 aStyleSettings.SetSelectionOptions(
2451 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2452 aSettings.SetStyleSettings(aStyleSettings);
2453 m_pWindow->SetSettings(aSettings, true);
2455 // some initial properties
2456 Reference< XPropertySet > xModel(m_rColumn.getModel());
2457 SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) );
2458 implAdjustGenericFieldSetting( xModel );
2460 DbCellControl::Init( rParent, xCursor );
2464 CellControllerRef DbComboBox::CreateController() const
2466 return new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2470 OUString DbComboBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, Color** /*ppColor*/)
2472 const css::uno::Reference<css::beans::XPropertySet> xPS(_rxField, UNO_QUERY);
2473 ::dbtools::FormattedColumnValue fmter( xFormatter, xPS );
2475 return fmter.getFormattedValue();
2479 void DbComboBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
2481 m_pWindow->SetText(GetFormatText(_rxField, xFormatter));
2485 void DbComboBox::updateFromModel( Reference< XPropertySet > _rxModel )
2487 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbComboBox::updateFromModel: invalid call!" );
2489 OUString sText;
2490 _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText;
2492 static_cast< ComboBox* >( m_pWindow.get() )->SetText( sText );
2493 static_cast< ComboBox* >( m_pWindow.get() )->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) );
2497 bool DbComboBox::commitControl()
2499 OUString aText( m_pWindow->GetText());
2500 m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, makeAny(aText));
2501 return true;
2505 DbListBox::DbListBox(DbGridColumn& _rColumn)
2506 :DbCellControl(_rColumn)
2507 ,m_bBound(false)
2509 setAlignedController( false );
2511 doPropertyListening( FM_PROP_STRINGITEMLIST );
2512 doPropertyListening( FM_PROP_LINECOUNT );
2516 void DbListBox::_propertyChanged( const css::beans::PropertyChangeEvent& _rEvent )
2518 if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST )
2520 SetList(_rEvent.NewValue);
2522 else
2524 DbCellControl::_propertyChanged( _rEvent ) ;
2529 void DbListBox::SetList(const Any& rItems)
2531 ListBoxControl* pField = static_cast<ListBoxControl*>(m_pWindow.get());
2533 pField->Clear();
2534 m_bBound = false;
2536 css::uno::Sequence<OUString> aTest;
2537 if (rItems >>= aTest)
2539 const OUString* pStrings = aTest.getConstArray();
2540 sal_Int32 nItems = aTest.getLength();
2541 if (nItems)
2543 for (sal_Int32 i = 0; i < nItems; ++i, ++pStrings )
2544 pField->InsertEntry(*pStrings);
2546 m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList;
2547 m_bBound = m_aValueList.getLength() > 0;
2549 // tell the grid control that this controller is invalid and has to be re-initialized
2550 invalidatedController();
2556 void DbListBox::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor)
2558 m_rColumn.SetAlignment(css::awt::TextAlign::LEFT);
2560 m_pWindow = VclPtr<ListBoxControl>::Create( &rParent );
2562 // some initial properties
2563 Reference< XPropertySet > xModel( m_rColumn.getModel() );
2564 SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) );
2565 implAdjustGenericFieldSetting( xModel );
2567 DbCellControl::Init( rParent, xCursor );
2571 void DbListBox::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel )
2573 DBG_ASSERT( m_pWindow, "DbListBox::implAdjustGenericFieldSetting: not to be called without window!" );
2574 DBG_ASSERT( _rxModel.is(), "DbListBox::implAdjustGenericFieldSetting: invalid model!" );
2575 if ( m_pWindow && _rxModel.is() )
2577 sal_Int16 nLines = getINT16( _rxModel->getPropertyValue( FM_PROP_LINECOUNT ) );
2578 static_cast< ListBoxControl* >( m_pWindow.get() )->SetDropDownLineCount( nLines );
2583 CellControllerRef DbListBox::CreateController() const
2585 return new ListBoxCellController(static_cast<ListBoxControl*>(m_pWindow.get()));
2589 OUString DbListBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
2591 OUString sText;
2592 if ( _rxField.is() )
2596 sText = _rxField->getString();
2597 if ( m_bBound )
2599 Sequence< sal_Int16 > aPosSeq = ::comphelper::findValue( m_aValueList, sText, true );
2600 if ( aPosSeq.getLength() )
2601 sText = static_cast<ListBox*>(m_pWindow.get())->GetEntry(aPosSeq.getConstArray()[0]);
2602 else
2603 sText.clear();
2606 catch( const Exception& )
2608 DBG_UNHANDLED_EXCEPTION();
2611 return sText;
2615 void DbListBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter)
2617 OUString sFormattedText( GetFormatText( _rxField, xFormatter ) );
2618 if (!sFormattedText.isEmpty())
2619 static_cast< ListBox* >( m_pWindow.get() )->SelectEntry( sFormattedText );
2620 else
2621 static_cast< ListBox* >( m_pWindow.get() )->SetNoSelection();
2625 void DbListBox::updateFromModel( Reference< XPropertySet > _rxModel )
2627 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbListBox::updateFromModel: invalid call!" );
2629 Sequence< sal_Int16 > aSelection;
2630 _rxModel->getPropertyValue( FM_PROP_SELECT_SEQ ) >>= aSelection;
2632 sal_Int16 nSelection = -1;
2633 if ( aSelection.getLength() > 0 )
2634 nSelection = aSelection[ 0 ];
2636 ListBox* pListBox = static_cast< ListBox* >( m_pWindow.get() );
2638 if ( ( nSelection >= 0 ) && ( nSelection < pListBox->GetEntryCount() ) )
2639 pListBox->SelectEntryPos( nSelection );
2640 else
2641 pListBox->SetNoSelection( );
2645 bool DbListBox::commitControl()
2647 Any aVal;
2648 Sequence<sal_Int16> aSelectSeq;
2649 if (static_cast<ListBox*>(m_pWindow.get())->GetSelectEntryCount())
2651 aSelectSeq.realloc(1);
2652 *aSelectSeq.getArray() = (sal_Int16)static_cast<ListBox*>(m_pWindow.get())->GetSelectEntryPos();
2654 aVal <<= aSelectSeq;
2655 m_rColumn.getModel()->setPropertyValue(FM_PROP_SELECT_SEQ, aVal);
2656 return true;
2659 DbFilterField::DbFilterField(const Reference< XComponentContext >& rxContext,DbGridColumn& _rColumn)
2660 :DbCellControl(_rColumn)
2661 ,OSQLParserClient(rxContext)
2662 ,m_nControlClass(css::form::FormComponentType::TEXTFIELD)
2663 ,m_bFilterList(false)
2664 ,m_bFilterListFilled(false)
2665 ,m_bBound(false)
2668 setAlignedController( false );
2672 DbFilterField::~DbFilterField()
2674 if (m_nControlClass == css::form::FormComponentType::CHECKBOX)
2675 static_cast<CheckBoxControl*>(m_pWindow.get())->SetClickHdl( Link<VclPtr<CheckBox>,void>() );
2680 void DbFilterField::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect)
2682 static const DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter | DrawTextFlags::Left;
2683 switch (m_nControlClass)
2685 case FormComponentType::CHECKBOX:
2686 DbCellControl::PaintCell( rDev, rRect );
2687 break;
2688 case FormComponentType::LISTBOX:
2689 rDev.DrawText(rRect, static_cast<ListBox*>(m_pWindow.get())->GetSelectEntry(), nStyle);
2690 break;
2691 default:
2692 rDev.DrawText(rRect, m_aText, nStyle);
2697 void DbFilterField::SetList(const Any& rItems, bool bComboBox)
2699 css::uno::Sequence<OUString> aTest;
2700 rItems >>= aTest;
2701 const OUString* pStrings = aTest.getConstArray();
2702 sal_Int32 nItems = aTest.getLength();
2703 if (nItems)
2705 if (bComboBox)
2707 ComboBox* pField = static_cast<ComboBox*>(m_pWindow.get());
2708 for (sal_Int32 i = 0; i < nItems; ++i, ++pStrings )
2709 pField->InsertEntry(*pStrings);
2711 else
2713 ListBox* pField = static_cast<ListBox*>(m_pWindow.get());
2714 for (sal_Int32 i = 0; i < nItems; ++i, ++pStrings )
2715 pField->InsertEntry(*pStrings);
2717 m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList;
2718 m_bBound = m_aValueList.getLength() > 0;
2724 void DbFilterField::CreateControl(vcl::Window* pParent, const Reference< css::beans::XPropertySet >& xModel)
2726 switch (m_nControlClass)
2728 case css::form::FormComponentType::CHECKBOX:
2729 m_pWindow = VclPtr<CheckBoxControl>::Create(pParent);
2730 m_pWindow->SetPaintTransparent( true );
2731 static_cast<CheckBoxControl*>(m_pWindow.get())->SetClickHdl( LINK( this, DbFilterField, OnClick ) );
2733 m_pPainter = VclPtr<CheckBoxControl>::Create(pParent);
2734 m_pPainter->SetPaintTransparent( true );
2735 m_pPainter->SetBackground();
2736 break;
2737 case css::form::FormComponentType::LISTBOX:
2739 m_pWindow = VclPtr<ListBoxControl>::Create(pParent);
2740 sal_Int16 nLines = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_LINECOUNT));
2741 Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST);
2742 SetList(aItems, m_nControlClass == css::form::FormComponentType::COMBOBOX);
2743 static_cast<ListBox*>(m_pWindow.get())->SetDropDownLineCount(nLines);
2744 } break;
2745 case css::form::FormComponentType::COMBOBOX:
2747 m_pWindow = VclPtr<ComboBoxControl>::Create(pParent);
2749 AllSettings aSettings = m_pWindow->GetSettings();
2750 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2751 aStyleSettings.SetSelectionOptions(
2752 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2753 aSettings.SetStyleSettings(aStyleSettings);
2754 m_pWindow->SetSettings(aSettings, true);
2756 if (!m_bFilterList)
2758 sal_Int16 nLines = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_LINECOUNT));
2759 Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST);
2760 SetList(aItems, m_nControlClass == css::form::FormComponentType::COMBOBOX);
2761 static_cast<ComboBox*>(m_pWindow.get())->SetDropDownLineCount(nLines);
2763 else
2764 static_cast<ComboBox*>(m_pWindow.get())->SetDropDownLineCount(5);
2766 } break;
2767 default:
2769 m_pWindow = VclPtr<Edit>::Create(pParent, WB_LEFT);
2770 AllSettings aSettings = m_pWindow->GetSettings();
2771 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2772 aStyleSettings.SetSelectionOptions(
2773 aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst);
2774 aSettings.SetStyleSettings(aStyleSettings);
2775 m_pWindow->SetSettings(aSettings, true);
2781 void DbFilterField::Init( vcl::Window& rParent, const Reference< XRowSet >& xCursor )
2783 Reference< css::beans::XPropertySet > xModel(m_rColumn.getModel());
2784 m_rColumn.SetAlignment(css::awt::TextAlign::LEFT);
2786 if (xModel.is())
2788 m_bFilterList = ::comphelper::hasProperty(FM_PROP_FILTERPROPOSAL, xModel) && ::comphelper::getBOOL(xModel->getPropertyValue(FM_PROP_FILTERPROPOSAL));
2789 if (m_bFilterList)
2790 m_nControlClass = css::form::FormComponentType::COMBOBOX;
2791 else
2793 sal_Int16 nClassId = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_CLASSID));
2794 switch (nClassId)
2796 case FormComponentType::CHECKBOX:
2797 case FormComponentType::LISTBOX:
2798 case FormComponentType::COMBOBOX:
2799 m_nControlClass = nClassId;
2800 break;
2801 default:
2802 if (m_bFilterList)
2803 m_nControlClass = FormComponentType::COMBOBOX;
2804 else
2805 m_nControlClass = FormComponentType::TEXTFIELD;
2810 CreateControl( &rParent, xModel );
2811 DbCellControl::Init( rParent, xCursor );
2813 // filter cells are never readonly
2814 Edit* pAsEdit = dynamic_cast< Edit* >( m_pWindow.get() );
2815 if ( pAsEdit )
2816 pAsEdit->SetReadOnly( false );
2820 CellControllerRef DbFilterField::CreateController() const
2822 CellControllerRef xController;
2823 switch (m_nControlClass)
2825 case css::form::FormComponentType::CHECKBOX:
2826 xController = new CheckBoxCellController(static_cast<CheckBoxControl*>(m_pWindow.get()));
2827 break;
2828 case css::form::FormComponentType::LISTBOX:
2829 xController = new ListBoxCellController(static_cast<ListBoxControl*>(m_pWindow.get()));
2830 break;
2831 case css::form::FormComponentType::COMBOBOX:
2832 xController = new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2833 break;
2834 default:
2835 if (m_bFilterList)
2836 xController = new ComboBoxCellController(static_cast<ComboBoxControl*>(m_pWindow.get()));
2837 else
2838 xController = new EditCellController(static_cast<Edit*>(m_pWindow.get()));
2840 return xController;
2844 void DbFilterField::updateFromModel( Reference< XPropertySet > _rxModel )
2846 OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFilterField::updateFromModel: invalid call!" );
2847 (void)_rxModel;
2849 OSL_FAIL( "DbListBox::updateFromModel: not implemented yet (how the hell did you reach this?)!" );
2850 // TODO: implement this.
2851 // remember: updateFromModel should be some kind of opposite of commitControl
2855 bool DbFilterField::commitControl()
2857 OUString aText(m_aText);
2858 switch (m_nControlClass)
2860 case css::form::FormComponentType::CHECKBOX:
2861 return true;
2862 case css::form::FormComponentType::LISTBOX:
2863 aText.clear();
2864 if (static_cast<ListBox*>(m_pWindow.get())->GetSelectEntryCount())
2866 sal_Int16 nPos = (sal_Int16)static_cast<ListBox*>(m_pWindow.get())->GetSelectEntryPos();
2867 if ( ( nPos >= 0 ) && ( nPos < m_aValueList.getLength() ) )
2868 aText = m_aValueList.getConstArray()[nPos];
2871 if (m_aText != aText)
2873 m_aText = aText;
2874 m_aCommitLink.Call(*this);
2876 return true;
2877 default:
2878 aText = m_pWindow->GetText();
2881 if (m_aText != aText)
2883 // check the text with the SQL-Parser
2884 OUString aNewText(comphelper::string::stripEnd(aText, ' '));
2885 if (!aNewText.isEmpty())
2887 OUString aErrorMsg;
2888 Reference< XNumberFormatter > xNumberFormatter(m_rColumn.GetParent().getNumberFormatter());
2890 std::shared_ptr< OSQLParseNode > pParseNode = predicateTree(aErrorMsg, aNewText,xNumberFormatter, m_rColumn.GetField());
2891 if (pParseNode != nullptr)
2893 OUString aPreparedText;
2895 css::lang::Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
2897 Reference< XRowSet > xDataSourceRowSet(
2898 Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY);
2899 Reference< XConnection > xConnection(getConnection(xDataSourceRowSet));
2901 pParseNode->parseNodeToPredicateStr(aPreparedText,
2902 xConnection,
2903 xNumberFormatter,
2904 m_rColumn.GetField(),
2905 OUString(),
2906 aAppLocale,
2907 '.',
2908 getParseContext());
2909 m_aText = aPreparedText;
2911 else
2914 SQLException aError;
2915 aError.Message = aErrorMsg;
2916 displayException(aError, m_pWindow->GetParent());
2917 // TODO: transport the title
2919 return false;
2922 else
2923 m_aText = aText;
2925 m_pWindow->SetText(m_aText);
2926 m_aCommitLink.Call(*this);
2928 return true;
2932 void DbFilterField::SetText(const OUString& rText)
2934 m_aText = rText;
2935 switch (m_nControlClass)
2937 case css::form::FormComponentType::CHECKBOX:
2939 TriState eState;
2940 if (rText == "1")
2941 eState = TRISTATE_TRUE;
2942 else if (rText == "0")
2943 eState = TRISTATE_FALSE;
2944 else
2945 eState = TRISTATE_INDET;
2947 static_cast<CheckBoxControl*>(m_pWindow.get())->GetBox().SetState(eState);
2948 static_cast<CheckBoxControl*>(m_pPainter.get())->GetBox().SetState(eState);
2949 } break;
2950 case css::form::FormComponentType::LISTBOX:
2952 Sequence<sal_Int16> aPosSeq = ::comphelper::findValue(m_aValueList, m_aText, true);
2953 if (aPosSeq.getLength())
2954 static_cast<ListBox*>(m_pWindow.get())->SelectEntryPos(aPosSeq.getConstArray()[0]);
2955 else
2956 static_cast<ListBox*>(m_pWindow.get())->SetNoSelection();
2957 } break;
2958 default:
2959 m_pWindow->SetText(m_aText);
2962 // now force a repaint on the window
2963 m_rColumn.GetParent().RowModified(0);
2967 void DbFilterField::Update()
2969 // should we fill the combobox with a filter proposal?
2970 if (m_bFilterList && !m_bFilterListFilled)
2972 m_bFilterListFilled = true;
2973 Reference< css::beans::XPropertySet > xField = m_rColumn.GetField();
2974 if (!xField.is())
2975 return;
2977 OUString aName;
2978 xField->getPropertyValue(FM_PROP_NAME) >>= aName;
2980 // the columnmodel
2981 Reference< css::container::XChild > xModelAsChild(m_rColumn.getModel(), UNO_QUERY);
2982 // the grid model
2983 xModelAsChild.set(xModelAsChild->getParent(),UNO_QUERY);
2984 Reference< XRowSet > xForm(xModelAsChild->getParent(), UNO_QUERY);
2985 if (!xForm.is())
2986 return;
2988 Reference<XPropertySet> xFormProp(xForm,UNO_QUERY);
2989 Reference< XTablesSupplier > xSupTab;
2990 xFormProp->getPropertyValue("SingleSelectQueryComposer") >>= xSupTab;
2992 Reference< XConnection > xConnection(getConnection(xForm));
2993 if (!xSupTab.is())
2994 return;
2996 // search the field
2997 Reference< XColumnsSupplier > xSupCol(xSupTab,UNO_QUERY);
2998 Reference< css::container::XNameAccess > xFieldNames = xSupCol->getColumns();
2999 if (!xFieldNames->hasByName(aName))
3000 return;
3002 Reference< css::container::XNameAccess > xTablesNames = xSupTab->getTables();
3003 Reference< css::beans::XPropertySet > xComposerFieldAsSet(xFieldNames->getByName(aName),UNO_QUERY);
3005 if (xComposerFieldAsSet.is() && ::comphelper::hasProperty(FM_PROP_TABLENAME, xComposerFieldAsSet) &&
3006 ::comphelper::hasProperty(FM_PROP_FIELDSOURCE, xComposerFieldAsSet))
3008 OUString aFieldName;
3009 OUString aTableName;
3010 xComposerFieldAsSet->getPropertyValue(FM_PROP_FIELDSOURCE) >>= aFieldName;
3011 xComposerFieldAsSet->getPropertyValue(FM_PROP_TABLENAME) >>= aTableName;
3013 // no possibility to create a select statement
3014 // looking for the complete table name
3015 if (!xTablesNames->hasByName(aTableName))
3016 return;
3018 // build a statement and send as query;
3019 // Access to the connection
3020 Reference< XStatement > xStatement;
3021 Reference< XResultSet > xListCursor;
3022 Reference< css::sdb::XColumn > xDataField;
3026 Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData();
3028 OUString aQuote(xMeta->getIdentifierQuoteString());
3029 OUStringBuffer aStatement("SELECT DISTINCT ");
3030 aStatement.append(quoteName(aQuote, aName));
3031 if (!aFieldName.isEmpty() && aName != aFieldName)
3033 aStatement.append(" AS ");
3034 aStatement.append(quoteName(aQuote, aFieldName));
3037 aStatement.append(" FROM ");
3039 Reference< XPropertySet > xTableNameAccess(xTablesNames->getByName(aTableName), UNO_QUERY_THROW);
3040 aStatement.append(composeTableNameForSelect(xConnection, xTableNameAccess));
3042 xStatement = xConnection->createStatement();
3043 Reference< css::beans::XPropertySet > xStatementProps(xStatement, UNO_QUERY);
3044 xStatementProps->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, makeAny(true));
3046 xListCursor = xStatement->executeQuery(aStatement.makeStringAndClear());
3048 Reference< css::sdbcx::XColumnsSupplier > xSupplyCols(xListCursor, UNO_QUERY);
3049 Reference< css::container::XIndexAccess > xFields(xSupplyCols->getColumns(), UNO_QUERY);
3050 xDataField.set(xFields->getByIndex(0), css::uno::UNO_QUERY);
3051 if (!xDataField.is())
3052 return;
3054 catch(const Exception&)
3056 ::comphelper::disposeComponent(xStatement);
3057 return;
3060 sal_Int16 i = 0;
3061 ::std::vector< OUString > aStringList;
3062 aStringList.reserve(16);
3063 OUString aStr;
3064 css::util::Date aNullDate = m_rColumn.GetParent().getNullDate();
3065 sal_Int32 nFormatKey = m_rColumn.GetKey();
3066 Reference< XNumberFormatter > xFormatter = m_rColumn.GetParent().getNumberFormatter();
3067 sal_Int16 nKeyType = ::comphelper::getNumberFormatType(xFormatter->getNumberFormatsSupplier()->getNumberFormats(), nFormatKey);
3069 while (!xListCursor->isAfterLast() && i++ < SHRT_MAX) // max anzahl eintraege
3071 aStr = getFormattedValue(xDataField, xFormatter, aNullDate, nFormatKey, nKeyType);
3072 aStringList.push_back(aStr);
3073 (void)xListCursor->next();
3076 // filling the entries for the combobox
3077 for (::std::vector< OUString >::const_iterator iter = aStringList.begin();
3078 iter != aStringList.end(); ++iter)
3079 static_cast<ComboBox*>(m_pWindow.get())->InsertEntry(*iter);
3085 OUString DbFilterField::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, Color** /*ppColor*/)
3087 return OUString();
3091 void DbFilterField::UpdateFromField(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/)
3093 OSL_FAIL( "DbFilterField::UpdateFromField: cannot update a filter control from a field!" );
3097 IMPL_LINK_NOARG(DbFilterField, OnClick, VclPtr<CheckBox>, void)
3099 TriState eState = static_cast<CheckBoxControl*>(m_pWindow.get())->GetBox().GetState();
3100 OUString aText;
3102 switch (eState)
3104 case TRISTATE_TRUE:
3105 aText = "1";
3106 break;
3107 case TRISTATE_FALSE:
3108 aText = "0";
3109 break;
3110 case TRISTATE_INDET:
3111 break;
3114 if (m_aText != aText)
3116 m_aText = aText;
3117 m_aCommitLink.Call(*this);
3122 FmXGridCell::FmXGridCell( DbGridColumn* pColumn, DbCellControl* _pControl )
3123 :OComponentHelper(m_aMutex)
3124 ,m_pColumn(pColumn)
3125 ,m_pCellControl( _pControl )
3126 ,m_aWindowListeners( m_aMutex )
3127 ,m_aFocusListeners( m_aMutex )
3128 ,m_aKeyListeners( m_aMutex )
3129 ,m_aMouseListeners( m_aMutex )
3130 ,m_aMouseMotionListeners( m_aMutex )
3135 void FmXGridCell::init()
3137 vcl::Window* pEventWindow( getEventWindow() );
3138 if ( pEventWindow )
3139 pEventWindow->AddEventListener( LINK( this, FmXGridCell, OnWindowEvent ) );
3143 vcl::Window* FmXGridCell::getEventWindow() const
3145 if ( m_pCellControl )
3146 return &m_pCellControl->GetWindow();
3147 return nullptr;
3151 FmXGridCell::~FmXGridCell()
3153 if (!OComponentHelper::rBHelper.bDisposed)
3155 acquire();
3156 dispose();
3162 void FmXGridCell::SetTextLineColor()
3164 if (m_pCellControl)
3165 m_pCellControl->SetTextLineColor();
3169 void FmXGridCell::SetTextLineColor(const Color& _rColor)
3171 if (m_pCellControl)
3172 m_pCellControl->SetTextLineColor(_rColor);
3175 // XTypeProvider
3177 Sequence< Type > SAL_CALL FmXGridCell::getTypes( )
3179 Sequence< uno::Type > aTypes = ::comphelper::concatSequences(
3180 ::cppu::OComponentHelper::getTypes(),
3181 FmXGridCell_Base::getTypes()
3183 if ( m_pCellControl )
3184 aTypes = ::comphelper::concatSequences(
3185 aTypes,
3186 FmXGridCell_WindowBase::getTypes()
3188 return aTypes;
3192 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXGridCell )
3194 // OComponentHelper
3196 void FmXGridCell::disposing()
3198 lang::EventObject aEvent( *this );
3199 m_aWindowListeners.disposeAndClear( aEvent );
3200 m_aFocusListeners.disposeAndClear( aEvent );
3201 m_aKeyListeners.disposeAndClear( aEvent );
3202 m_aMouseListeners.disposeAndClear( aEvent );
3203 m_aMouseMotionListeners.disposeAndClear( aEvent );
3205 OComponentHelper::disposing();
3206 m_pColumn = nullptr;
3207 DELETEZ(m_pCellControl);
3211 Any SAL_CALL FmXGridCell::queryAggregation( const css::uno::Type& _rType )
3213 Any aReturn = OComponentHelper::queryAggregation( _rType );
3215 if ( !aReturn.hasValue() )
3216 aReturn = FmXGridCell_Base::queryInterface( _rType );
3218 if ( !aReturn.hasValue() && ( m_pCellControl != nullptr ) )
3219 aReturn = FmXGridCell_WindowBase::queryInterface( _rType );
3221 return aReturn;
3224 // css::awt::XControl
3226 Reference< XInterface > FmXGridCell::getContext()
3228 return Reference< XInterface > ();
3232 Reference< css::awt::XControlModel > FmXGridCell::getModel()
3234 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3235 return Reference< css::awt::XControlModel > (m_pColumn->getModel(), UNO_QUERY);
3238 // css::form::XBoundControl
3240 sal_Bool FmXGridCell::getLock()
3242 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3243 return m_pColumn->isLocked();
3247 void FmXGridCell::setLock(sal_Bool _bLock)
3249 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3250 if (getLock() == _bLock)
3251 return;
3252 else
3254 ::osl::MutexGuard aGuard(m_aMutex);
3255 m_pColumn->setLock(_bLock);
3260 void SAL_CALL FmXGridCell::setPosSize( ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int16 )
3262 OSL_FAIL( "FmXGridCell::setPosSize: not implemented" );
3263 // not allowed to tamper with this for a grid cell
3267 awt::Rectangle SAL_CALL FmXGridCell::getPosSize( )
3269 OSL_FAIL( "FmXGridCell::getPosSize: not implemented" );
3270 return awt::Rectangle();
3274 void SAL_CALL FmXGridCell::setVisible( sal_Bool )
3276 OSL_FAIL( "FmXGridCell::setVisible: not implemented" );
3277 // not allowed to tamper with this for a grid cell
3281 void SAL_CALL FmXGridCell::setEnable( sal_Bool )
3283 OSL_FAIL( "FmXGridCell::setEnable: not implemented" );
3284 // not allowed to tamper with this for a grid cell
3288 void SAL_CALL FmXGridCell::setFocus( )
3290 OSL_FAIL( "FmXGridCell::setFocus: not implemented" );
3291 // not allowed to tamper with this for a grid cell
3295 void SAL_CALL FmXGridCell::addWindowListener( const Reference< awt::XWindowListener >& _rxListener )
3297 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3298 m_aWindowListeners.addInterface( _rxListener );
3302 void SAL_CALL FmXGridCell::removeWindowListener( const Reference< awt::XWindowListener >& _rxListener )
3304 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3305 m_aWindowListeners.removeInterface( _rxListener );
3309 void SAL_CALL FmXGridCell::addFocusListener( const Reference< awt::XFocusListener >& _rxListener )
3311 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3312 m_aFocusListeners.addInterface( _rxListener );
3316 void SAL_CALL FmXGridCell::removeFocusListener( const Reference< awt::XFocusListener >& _rxListener )
3318 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3319 m_aFocusListeners.removeInterface( _rxListener );
3323 void SAL_CALL FmXGridCell::addKeyListener( const Reference< awt::XKeyListener >& _rxListener )
3325 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3326 m_aKeyListeners.addInterface( _rxListener );
3330 void SAL_CALL FmXGridCell::removeKeyListener( const Reference< awt::XKeyListener >& _rxListener )
3332 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3333 m_aKeyListeners.removeInterface( _rxListener );
3337 void SAL_CALL FmXGridCell::addMouseListener( const Reference< awt::XMouseListener >& _rxListener )
3339 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3340 m_aMouseListeners.addInterface( _rxListener );
3344 void SAL_CALL FmXGridCell::removeMouseListener( const Reference< awt::XMouseListener >& _rxListener )
3346 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3347 m_aMouseListeners.removeInterface( _rxListener );
3351 void SAL_CALL FmXGridCell::addMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener )
3353 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3354 m_aMouseMotionListeners.addInterface( _rxListener );
3358 void SAL_CALL FmXGridCell::removeMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener )
3360 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3361 m_aMouseMotionListeners.removeInterface( _rxListener );
3365 void SAL_CALL FmXGridCell::addPaintListener( const Reference< awt::XPaintListener >& _rxListener )
3367 OSL_FAIL( "FmXGridCell::addPaintListener: not implemented" );
3368 (void)_rxListener;
3372 void SAL_CALL FmXGridCell::removePaintListener( const Reference< awt::XPaintListener >& _rxListener )
3374 OSL_FAIL( "FmXGridCell::removePaintListener: not implemented" );
3375 (void)_rxListener;
3379 IMPL_LINK( FmXGridCell, OnWindowEvent, VclWindowEvent&, _rEvent, void )
3381 ENSURE_OR_THROW( _rEvent.GetWindow(), "illegal window" );
3382 onWindowEvent( _rEvent.GetId(), *_rEvent.GetWindow(), _rEvent.GetData() );
3386 void FmXGridCell::onFocusGained( const awt::FocusEvent& _rEvent )
3388 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3389 m_aFocusListeners.notifyEach( &awt::XFocusListener::focusGained, _rEvent );
3393 void FmXGridCell::onFocusLost( const awt::FocusEvent& _rEvent )
3395 checkDisposed(OComponentHelper::rBHelper.bDisposed);
3396 m_aFocusListeners.notifyEach( &awt::XFocusListener::focusLost, _rEvent );
3400 void FmXGridCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
3402 switch ( _nEventId )
3404 case VclEventId::ControlGetFocus:
3405 case VclEventId::WindowGetFocus:
3406 case VclEventId::ControlLoseFocus:
3407 case VclEventId::WindowLoseFocus:
3409 if ( ( _rWindow.IsCompoundControl()
3410 && ( _nEventId == VclEventId::ControlGetFocus
3411 || _nEventId == VclEventId::ControlLoseFocus
3414 || ( !_rWindow.IsCompoundControl()
3415 && ( _nEventId == VclEventId::WindowGetFocus
3416 || _nEventId == VclEventId::WindowLoseFocus
3421 if ( !m_aFocusListeners.getLength() )
3422 break;
3424 bool bFocusGained = ( _nEventId == VclEventId::ControlGetFocus ) || ( _nEventId == VclEventId::WindowGetFocus );
3426 awt::FocusEvent aEvent;
3427 aEvent.Source = *this;
3428 aEvent.FocusFlags = static_cast<sal_Int16>(_rWindow.GetGetFocusFlags());
3429 aEvent.Temporary = false;
3431 if ( bFocusGained )
3432 onFocusGained( aEvent );
3433 else
3434 onFocusLost( aEvent );
3437 break;
3438 case VclEventId::WindowMouseButtonDown:
3439 case VclEventId::WindowMouseButtonUp:
3441 if ( !m_aMouseListeners.getLength() )
3442 break;
3444 const bool bButtonDown = ( _nEventId == VclEventId::WindowMouseButtonDown );
3446 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast< const ::MouseEvent* >( _pEventData ), *this ) );
3447 m_aMouseListeners.notifyEach( bButtonDown ? &awt::XMouseListener::mousePressed : &awt::XMouseListener::mouseReleased, aEvent );
3449 break;
3450 case VclEventId::WindowMouseMove:
3452 const MouseEvent& rMouseEvent = *static_cast< const ::MouseEvent* >( _pEventData );
3453 if ( rMouseEvent.IsEnterWindow() || rMouseEvent.IsLeaveWindow() )
3455 if ( m_aMouseListeners.getLength() != 0 )
3457 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) );
3458 m_aMouseListeners.notifyEach( rMouseEvent.IsEnterWindow() ? &awt::XMouseListener::mouseEntered: &awt::XMouseListener::mouseExited, aEvent );
3461 else if ( !rMouseEvent.IsEnterWindow() && !rMouseEvent.IsLeaveWindow() )
3463 if ( m_aMouseMotionListeners.getLength() != 0 )
3465 awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) );
3466 aEvent.ClickCount = 0;
3467 const bool bSimpleMove = bool( rMouseEvent.GetMode() & MouseEventModifiers::SIMPLEMOVE );
3468 m_aMouseMotionListeners.notifyEach( bSimpleMove ? &awt::XMouseMotionListener::mouseMoved: &awt::XMouseMotionListener::mouseDragged, aEvent );
3472 break;
3473 case VclEventId::WindowKeyInput:
3474 case VclEventId::WindowKeyUp:
3476 if ( !m_aKeyListeners.getLength() )
3477 break;
3479 const bool bKeyPressed = ( _nEventId == VclEventId::WindowKeyInput );
3480 awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent( *static_cast< const ::KeyEvent* >( _pEventData ), *this ) );
3481 m_aKeyListeners.notifyEach( bKeyPressed ? &awt::XKeyListener::keyPressed: &awt::XKeyListener::keyReleased, aEvent );
3483 break;
3484 default: break;
3489 void FmXDataCell::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect,
3490 const Reference< css::sdb::XColumn >& _rxField,
3491 const Reference< XNumberFormatter >& xFormatter)
3493 m_pCellControl->PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
3497 void FmXDataCell::UpdateFromColumn()
3499 Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue());
3500 if (xField.is())
3501 m_pCellControl->UpdateFromField(xField, m_pColumn->GetParent().getNumberFormatter());
3505 FmXTextCell::FmXTextCell( DbGridColumn* pColumn, DbCellControl& _rControl )
3506 :FmXDataCell( pColumn, _rControl )
3507 ,m_bFastPaint( true )
3512 void FmXTextCell::PaintFieldToCell(OutputDevice& rDev,
3513 const tools::Rectangle& rRect,
3514 const Reference< css::sdb::XColumn >& _rxField,
3515 const Reference< XNumberFormatter >& xFormatter)
3517 if ( !m_bFastPaint )
3519 FmXDataCell::PaintFieldToCell( rDev, rRect, _rxField, xFormatter );
3520 return;
3523 DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter;
3524 if ( ( rDev.GetOutDevType() == OUTDEV_WINDOW ) && !static_cast< vcl::Window& >( rDev ).IsEnabled() )
3525 nStyle |= DrawTextFlags::Disable;
3527 switch (m_pColumn->GetAlignment())
3529 case css::awt::TextAlign::RIGHT:
3530 nStyle |= DrawTextFlags::Right;
3531 break;
3532 case css::awt::TextAlign::CENTER:
3533 nStyle |= DrawTextFlags::Center;
3534 break;
3535 default:
3536 nStyle |= DrawTextFlags::Left;
3541 Color* pColor = nullptr;
3542 OUString aText = GetText(_rxField, xFormatter, &pColor);
3543 if (pColor != nullptr)
3545 Color aOldTextColor( rDev.GetTextColor() );
3546 rDev.SetTextColor( *pColor );
3547 rDev.DrawText(rRect, aText, nStyle);
3548 rDev.SetTextColor( aOldTextColor );
3550 else
3551 rDev.DrawText(rRect, aText, nStyle);
3553 catch (const Exception& e)
3555 SAL_WARN("svx.fmcomp", "PaintFieldToCell: caught an exception: " << e.Message);
3559 FmXEditCell::FmXEditCell( DbGridColumn* pColumn, DbCellControl& _rControl )
3560 :FmXTextCell( pColumn, _rControl )
3561 ,m_aTextListeners(m_aMutex)
3562 ,m_aChangeListeners( m_aMutex )
3563 ,m_pEditImplementation( nullptr )
3564 ,m_bOwnEditImplementation( false )
3567 DbTextField* pTextField = dynamic_cast<DbTextField*>( &_rControl );
3568 if ( pTextField )
3571 m_pEditImplementation = pTextField->GetEditImplementation();
3572 if ( !pTextField->IsSimpleEdit() )
3573 m_bFastPaint = false;
3575 else
3577 m_pEditImplementation = new EditImplementation( static_cast< Edit& >( _rControl.GetWindow() ) );
3578 m_bOwnEditImplementation = true;
3583 FmXEditCell::~FmXEditCell()
3585 if (!OComponentHelper::rBHelper.bDisposed)
3587 acquire();
3588 dispose();
3594 // OComponentHelper
3596 void FmXEditCell::disposing()
3598 css::lang::EventObject aEvt(*this);
3599 m_aTextListeners.disposeAndClear(aEvt);
3600 m_aChangeListeners.disposeAndClear(aEvt);
3602 m_pEditImplementation->SetModifyHdl( Link<Edit&,void>() );
3603 if ( m_bOwnEditImplementation )
3604 delete m_pEditImplementation;
3605 m_pEditImplementation = nullptr;
3607 FmXDataCell::disposing();
3611 Any SAL_CALL FmXEditCell::queryAggregation( const css::uno::Type& _rType )
3613 Any aReturn = FmXTextCell::queryAggregation( _rType );
3615 if ( !aReturn.hasValue() )
3616 aReturn = FmXEditCell_Base::queryInterface( _rType );
3618 return aReturn;
3622 Sequence< css::uno::Type > SAL_CALL FmXEditCell::getTypes( )
3624 return ::comphelper::concatSequences(
3625 FmXTextCell::getTypes(),
3626 FmXEditCell_Base::getTypes()
3631 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXEditCell )
3633 // css::awt::XTextComponent
3635 void SAL_CALL FmXEditCell::addTextListener(const Reference< css::awt::XTextListener >& l)
3637 m_aTextListeners.addInterface( l );
3641 void SAL_CALL FmXEditCell::removeTextListener(const Reference< css::awt::XTextListener >& l)
3643 m_aTextListeners.removeInterface( l );
3647 void SAL_CALL FmXEditCell::setText( const OUString& aText )
3649 ::osl::MutexGuard aGuard( m_aMutex );
3651 if ( m_pEditImplementation )
3653 m_pEditImplementation->SetText( aText );
3655 // In Java, a textChanged is fired as well; not in VCL.
3656 // css::awt::Toolkit must be Java-compliant...
3657 onTextChanged();
3662 void SAL_CALL FmXEditCell::insertText(const css::awt::Selection& rSel, const OUString& aText)
3664 ::osl::MutexGuard aGuard( m_aMutex );
3666 if ( m_pEditImplementation )
3668 m_pEditImplementation->SetSelection( Selection( rSel.Min, rSel.Max ) );
3669 m_pEditImplementation->ReplaceSelected( aText );
3674 OUString SAL_CALL FmXEditCell::getText()
3676 ::osl::MutexGuard aGuard( m_aMutex );
3678 OUString aText;
3679 if ( m_pEditImplementation )
3681 if ( m_pEditImplementation->GetControl().IsVisible() && m_pColumn->GetParent().getDisplaySynchron())
3683 // if the display isn't sync with the cursor we can't ask the edit field
3684 LineEnd eLineEndFormat = getModelLineEndSetting( m_pColumn->getModel() );
3685 aText = m_pEditImplementation->GetText( eLineEndFormat );
3687 else
3689 Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue());
3690 if (xField.is())
3691 aText = GetText(xField, m_pColumn->GetParent().getNumberFormatter());
3694 return aText;
3698 OUString SAL_CALL FmXEditCell::getSelectedText()
3700 ::osl::MutexGuard aGuard( m_aMutex );
3702 OUString aText;
3703 if ( m_pEditImplementation )
3705 LineEnd eLineEndFormat = m_pColumn ? getModelLineEndSetting( m_pColumn->getModel() ) : LINEEND_LF;
3706 aText = m_pEditImplementation->GetSelected( eLineEndFormat );
3708 return aText;
3712 void SAL_CALL FmXEditCell::setSelection( const css::awt::Selection& aSelection )
3714 ::osl::MutexGuard aGuard( m_aMutex );
3716 if ( m_pEditImplementation )
3717 m_pEditImplementation->SetSelection( Selection( aSelection.Min, aSelection.Max ) );
3721 css::awt::Selection SAL_CALL FmXEditCell::getSelection()
3723 ::osl::MutexGuard aGuard( m_aMutex );
3725 Selection aSel;
3726 if ( m_pEditImplementation )
3727 aSel = m_pEditImplementation->GetSelection();
3729 return css::awt::Selection(aSel.Min(), aSel.Max());
3733 sal_Bool SAL_CALL FmXEditCell::isEditable()
3735 ::osl::MutexGuard aGuard( m_aMutex );
3737 return m_pEditImplementation && !m_pEditImplementation->IsReadOnly() && m_pEditImplementation->GetControl().IsEnabled();
3741 void SAL_CALL FmXEditCell::setEditable( sal_Bool bEditable )
3743 ::osl::MutexGuard aGuard( m_aMutex );
3745 if ( m_pEditImplementation )
3746 m_pEditImplementation->SetReadOnly( !bEditable );
3750 sal_Int16 SAL_CALL FmXEditCell::getMaxTextLen()
3752 ::osl::MutexGuard aGuard( m_aMutex );
3754 return m_pEditImplementation ? m_pEditImplementation->GetMaxTextLen() : 0;
3758 void SAL_CALL FmXEditCell::setMaxTextLen( sal_Int16 nLen )
3760 ::osl::MutexGuard aGuard( m_aMutex );
3762 if ( m_pEditImplementation )
3763 m_pEditImplementation->SetMaxTextLen( nLen );
3767 void SAL_CALL FmXEditCell::addChangeListener( const Reference< form::XChangeListener >& Listener )
3769 m_aChangeListeners.addInterface( Listener );
3773 void SAL_CALL FmXEditCell::removeChangeListener( const Reference< form::XChangeListener >& Listener )
3775 m_aChangeListeners.removeInterface( Listener );
3779 void FmXEditCell::onTextChanged()
3781 css::awt::TextEvent aEvent;
3782 aEvent.Source = *this;
3783 m_aTextListeners.notifyEach( &awt::XTextListener::textChanged, aEvent );
3787 void FmXEditCell::onFocusGained( const awt::FocusEvent& _rEvent )
3789 FmXTextCell::onFocusGained( _rEvent );
3790 m_sValueOnEnter = getText();
3794 void FmXEditCell::onFocusLost( const awt::FocusEvent& _rEvent )
3796 FmXTextCell::onFocusLost( _rEvent );
3798 if ( getText() != m_sValueOnEnter )
3800 lang::EventObject aEvent( *this );
3801 m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvent );
3806 void FmXEditCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
3808 switch ( _nEventId )
3810 case VclEventId::EditModify:
3812 if ( m_pEditImplementation && m_aTextListeners.getLength() )
3813 onTextChanged();
3814 return;
3816 default: break;
3819 FmXTextCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
3822 FmXCheckBoxCell::FmXCheckBoxCell( DbGridColumn* pColumn, DbCellControl& _rControl )
3823 :FmXDataCell( pColumn, _rControl )
3824 ,m_aItemListeners(m_aMutex)
3825 ,m_aActionListeners( m_aMutex )
3826 ,m_pBox( & static_cast< CheckBoxControl& >( _rControl.GetWindow() ).GetBox() )
3831 FmXCheckBoxCell::~FmXCheckBoxCell()
3833 if (!OComponentHelper::rBHelper.bDisposed)
3835 acquire();
3836 dispose();
3841 // OComponentHelper
3843 void FmXCheckBoxCell::disposing()
3845 css::lang::EventObject aEvt(*this);
3846 m_aItemListeners.disposeAndClear(aEvt);
3847 m_aActionListeners.disposeAndClear(aEvt);
3849 static_cast< CheckBoxControl& >( m_pCellControl->GetWindow() ).SetClickHdl(Link<VclPtr<CheckBox>,void>());
3850 m_pBox = nullptr;
3852 FmXDataCell::disposing();
3856 Any SAL_CALL FmXCheckBoxCell::queryAggregation( const css::uno::Type& _rType )
3858 Any aReturn = FmXDataCell::queryAggregation( _rType );
3860 if ( !aReturn.hasValue() )
3861 aReturn = FmXCheckBoxCell_Base::queryInterface( _rType );
3863 return aReturn;
3867 Sequence< css::uno::Type > SAL_CALL FmXCheckBoxCell::getTypes( )
3869 return ::comphelper::concatSequences(
3870 FmXDataCell::getTypes(),
3871 FmXCheckBoxCell_Base::getTypes()
3876 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXCheckBoxCell )
3879 void SAL_CALL FmXCheckBoxCell::addItemListener( const Reference< css::awt::XItemListener >& l )
3881 m_aItemListeners.addInterface( l );
3885 void SAL_CALL FmXCheckBoxCell::removeItemListener( const Reference< css::awt::XItemListener >& l )
3887 m_aItemListeners.removeInterface( l );
3891 void SAL_CALL FmXCheckBoxCell::setState( short n )
3893 ::osl::MutexGuard aGuard( m_aMutex );
3895 if (m_pBox)
3897 UpdateFromColumn();
3898 m_pBox->SetState( (TriState)n );
3903 short SAL_CALL FmXCheckBoxCell::getState()
3905 ::osl::MutexGuard aGuard( m_aMutex );
3907 if (m_pBox)
3909 UpdateFromColumn();
3910 return (short)m_pBox->GetState();
3912 return TRISTATE_INDET;
3916 void SAL_CALL FmXCheckBoxCell::enableTriState( sal_Bool b )
3918 ::osl::MutexGuard aGuard( m_aMutex );
3920 if (m_pBox)
3921 m_pBox->EnableTriState( b );
3925 void SAL_CALL FmXCheckBoxCell::addActionListener( const Reference< awt::XActionListener >& Listener )
3927 m_aActionListeners.addInterface( Listener );
3931 void SAL_CALL FmXCheckBoxCell::removeActionListener( const Reference< awt::XActionListener >& Listener )
3933 m_aActionListeners.removeInterface( Listener );
3937 void SAL_CALL FmXCheckBoxCell::setLabel( const OUString& Label )
3939 SolarMutexGuard aGuard;
3940 if ( m_pColumn )
3942 DbGridControl& rGrid( m_pColumn->GetParent() );
3943 rGrid.SetColumnTitle( rGrid.GetColumnId( m_pColumn->GetFieldPos() ), Label );
3948 void SAL_CALL FmXCheckBoxCell::setActionCommand( const OUString& Command )
3950 m_aActionCommand = Command;
3954 vcl::Window* FmXCheckBoxCell::getEventWindow() const
3956 return m_pBox;
3960 void FmXCheckBoxCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
3962 switch ( _nEventId )
3964 case VclEventId::CheckboxToggle:
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 );
3988 break;
3990 default:
3991 FmXDataCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
3992 break;
3996 FmXListBoxCell::FmXListBoxCell(DbGridColumn* pColumn, DbCellControl& _rControl)
3997 :FmXTextCell( pColumn, _rControl )
3998 ,m_aItemListeners(m_aMutex)
3999 ,m_aActionListeners(m_aMutex)
4000 ,m_pBox( &static_cast< ListBox& >( _rControl.GetWindow() ) )
4003 m_pBox->SetDoubleClickHdl( LINK( this, FmXListBoxCell, OnDoubleClick ) );
4007 FmXListBoxCell::~FmXListBoxCell()
4009 if (!OComponentHelper::rBHelper.bDisposed)
4011 acquire();
4012 dispose();
4017 // OComponentHelper
4019 void FmXListBoxCell::disposing()
4021 css::lang::EventObject aEvt(*this);
4022 m_aItemListeners.disposeAndClear(aEvt);
4023 m_aActionListeners.disposeAndClear(aEvt);
4025 m_pBox->SetSelectHdl( Link<ListBox&,void>() );
4026 m_pBox->SetDoubleClickHdl( Link<ListBox&,void>() );
4027 m_pBox = nullptr;
4029 FmXTextCell::disposing();
4033 Any SAL_CALL FmXListBoxCell::queryAggregation( const css::uno::Type& _rType )
4035 Any aReturn = FmXTextCell::queryAggregation(_rType);
4037 if ( !aReturn.hasValue() )
4038 aReturn = FmXListBoxCell_Base::queryInterface( _rType );
4040 return aReturn;
4044 Sequence< css::uno::Type > SAL_CALL FmXListBoxCell::getTypes( )
4046 return ::comphelper::concatSequences(
4047 FmXTextCell::getTypes(),
4048 FmXListBoxCell_Base::getTypes()
4053 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXListBoxCell )
4056 void SAL_CALL FmXListBoxCell::addItemListener(const Reference< css::awt::XItemListener >& l)
4058 m_aItemListeners.addInterface( l );
4062 void SAL_CALL FmXListBoxCell::removeItemListener(const Reference< css::awt::XItemListener >& l)
4064 m_aItemListeners.removeInterface( l );
4068 void SAL_CALL FmXListBoxCell::addActionListener(const Reference< css::awt::XActionListener >& l)
4070 m_aActionListeners.addInterface( l );
4074 void SAL_CALL FmXListBoxCell::removeActionListener(const Reference< css::awt::XActionListener >& l)
4076 m_aActionListeners.removeInterface( l );
4080 void SAL_CALL FmXListBoxCell::addItem(const OUString& aItem, sal_Int16 nPos)
4082 ::osl::MutexGuard aGuard( m_aMutex );
4083 if (m_pBox)
4084 m_pBox->InsertEntry( aItem, nPos );
4088 void SAL_CALL FmXListBoxCell::addItems(const css::uno::Sequence<OUString>& aItems, sal_Int16 nPos)
4090 ::osl::MutexGuard aGuard( m_aMutex );
4091 if (m_pBox)
4093 sal_uInt16 nP = nPos;
4094 for ( sal_Int32 n = 0; n < aItems.getLength(); n++ )
4096 m_pBox->InsertEntry( aItems.getConstArray()[n], nP );
4097 if ( nPos != -1 ) // Not if 0xFFFF, because LIST_APPEND
4098 nP++;
4104 void SAL_CALL FmXListBoxCell::removeItems(sal_Int16 nPos, sal_Int16 nCount)
4106 ::osl::MutexGuard aGuard( m_aMutex );
4107 if ( m_pBox )
4109 for ( sal_uInt16 n = nCount; n; )
4110 m_pBox->RemoveEntry( nPos + (--n) );
4115 sal_Int16 SAL_CALL FmXListBoxCell::getItemCount()
4117 ::osl::MutexGuard aGuard( m_aMutex );
4118 return m_pBox ? m_pBox->GetEntryCount() : 0;
4122 OUString SAL_CALL FmXListBoxCell::getItem(sal_Int16 nPos)
4124 ::osl::MutexGuard aGuard( m_aMutex );
4125 return m_pBox ? OUString(m_pBox->GetEntry(nPos)) : OUString();
4128 css::uno::Sequence<OUString> SAL_CALL FmXListBoxCell::getItems()
4130 ::osl::MutexGuard aGuard( m_aMutex );
4132 css::uno::Sequence<OUString> aSeq;
4133 if (m_pBox)
4135 const sal_Int32 nEntries = m_pBox ->GetEntryCount();
4136 aSeq = css::uno::Sequence<OUString>( nEntries );
4137 for ( sal_Int32 n = nEntries; n; )
4139 --n;
4140 aSeq.getArray()[n] = m_pBox ->GetEntry( n );
4143 return aSeq;
4147 sal_Int16 SAL_CALL FmXListBoxCell::getSelectedItemPos()
4149 ::osl::MutexGuard aGuard( m_aMutex );
4150 if (m_pBox)
4152 UpdateFromColumn();
4153 sal_Int32 nPos = m_pBox->GetSelectEntryPos();
4154 if (nPos > SHRT_MAX || nPos < SHRT_MIN)
4155 throw std::out_of_range("awt::XListBox::getSelectedItemPos can only return a short");
4156 return nPos;
4158 return 0;
4162 Sequence< sal_Int16 > SAL_CALL FmXListBoxCell::getSelectedItemsPos()
4164 ::osl::MutexGuard aGuard( m_aMutex );
4165 Sequence<sal_Int16> aSeq;
4167 if (m_pBox)
4169 UpdateFromColumn();
4170 const sal_Int32 nSelEntries = m_pBox->GetSelectEntryCount();
4171 aSeq = Sequence<sal_Int16>( nSelEntries );
4172 for ( sal_Int32 n = 0; n < nSelEntries; ++n )
4173 aSeq.getArray()[n] = m_pBox->GetSelectEntryPos( n );
4175 return aSeq;
4178 OUString SAL_CALL FmXListBoxCell::getSelectedItem()
4180 ::osl::MutexGuard aGuard( m_aMutex );
4182 OUString aItem;
4184 if (m_pBox)
4186 UpdateFromColumn();
4187 aItem = m_pBox->GetSelectEntry();
4190 return aItem;
4194 css::uno::Sequence<OUString> SAL_CALL FmXListBoxCell::getSelectedItems()
4196 ::osl::MutexGuard aGuard( m_aMutex );
4198 css::uno::Sequence<OUString> aSeq;
4200 if (m_pBox)
4202 UpdateFromColumn();
4203 const sal_Int32 nSelEntries = m_pBox->GetSelectEntryCount();
4204 aSeq = css::uno::Sequence<OUString>( nSelEntries );
4205 for ( sal_Int32 n = 0; n < nSelEntries; ++n )
4206 aSeq.getArray()[n] = m_pBox->GetSelectEntry( n );
4208 return aSeq;
4212 void SAL_CALL FmXListBoxCell::selectItemPos(sal_Int16 nPos, sal_Bool bSelect)
4214 ::osl::MutexGuard aGuard( m_aMutex );
4216 if (m_pBox)
4217 m_pBox->SelectEntryPos( nPos, bSelect );
4221 void SAL_CALL FmXListBoxCell::selectItemsPos(const Sequence< sal_Int16 >& aPositions, sal_Bool bSelect)
4223 ::osl::MutexGuard aGuard( m_aMutex );
4225 if (m_pBox)
4227 for ( sal_uInt16 n = (sal_uInt16)aPositions.getLength(); n; )
4228 m_pBox->SelectEntryPos( (sal_uInt16) aPositions.getConstArray()[--n], bSelect );
4233 void SAL_CALL FmXListBoxCell::selectItem(const OUString& aItem, sal_Bool bSelect)
4235 ::osl::MutexGuard aGuard( m_aMutex );
4237 if (m_pBox)
4238 m_pBox->SelectEntry( aItem, bSelect );
4242 sal_Bool SAL_CALL FmXListBoxCell::isMutipleMode()
4244 ::osl::MutexGuard aGuard( m_aMutex );
4246 bool bMulti = false;
4247 if (m_pBox)
4248 bMulti = m_pBox->IsMultiSelectionEnabled();
4249 return bMulti;
4253 void SAL_CALL FmXListBoxCell::setMultipleMode(sal_Bool bMulti)
4255 ::osl::MutexGuard aGuard( m_aMutex );
4257 if (m_pBox)
4258 m_pBox->EnableMultiSelection( bMulti );
4262 sal_Int16 SAL_CALL FmXListBoxCell::getDropDownLineCount()
4264 ::osl::MutexGuard aGuard( m_aMutex );
4266 sal_Int16 nLines = 0;
4267 if (m_pBox)
4268 nLines = m_pBox->GetDropDownLineCount();
4270 return nLines;
4274 void SAL_CALL FmXListBoxCell::setDropDownLineCount(sal_Int16 nLines)
4276 ::osl::MutexGuard aGuard( m_aMutex );
4278 if (m_pBox)
4279 m_pBox->SetDropDownLineCount( nLines );
4283 void SAL_CALL FmXListBoxCell::makeVisible(sal_Int16 nEntry)
4285 ::osl::MutexGuard aGuard( m_aMutex );
4287 if (m_pBox)
4288 m_pBox->SetTopEntry( nEntry );
4292 void FmXListBoxCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
4294 if ( ( &_rWindow == m_pBox )
4295 && ( _nEventId == VclEventId::ListboxSelect )
4298 OnDoubleClick( *m_pBox );
4300 css::awt::ItemEvent aEvent;
4301 aEvent.Source = *this;
4302 aEvent.Highlighted = 0;
4304 // with multiple selection 0xFFFF, otherwise the ID
4305 aEvent.Selected = (m_pBox->GetSelectEntryCount() == 1 )
4306 ? m_pBox->GetSelectEntryPos() : 0xFFFF;
4308 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
4309 return;
4312 FmXTextCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
4316 IMPL_LINK_NOARG(FmXListBoxCell, OnDoubleClick, ListBox&, void)
4318 if (m_pBox)
4320 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aActionListeners );
4322 css::awt::ActionEvent aEvent;
4323 aEvent.Source = *this;
4324 aEvent.ActionCommand = m_pBox->GetSelectEntry();
4326 while( aIt.hasMoreElements() )
4327 static_cast< css::awt::XActionListener *>(aIt.next())->actionPerformed( aEvent );
4331 FmXComboBoxCell::FmXComboBoxCell( DbGridColumn* pColumn, DbCellControl& _rControl )
4332 :FmXTextCell( pColumn, _rControl )
4333 ,m_aItemListeners( m_aMutex )
4334 ,m_aActionListeners( m_aMutex )
4335 ,m_pComboBox( &static_cast< ComboBox& >( _rControl.GetWindow() ) )
4340 FmXComboBoxCell::~FmXComboBoxCell()
4342 if ( !OComponentHelper::rBHelper.bDisposed )
4344 acquire();
4345 dispose();
4351 void FmXComboBoxCell::disposing()
4353 css::lang::EventObject aEvt(*this);
4354 m_aItemListeners.disposeAndClear(aEvt);
4355 m_aActionListeners.disposeAndClear(aEvt);
4357 FmXTextCell::disposing();
4361 Any SAL_CALL FmXComboBoxCell::queryAggregation( const css::uno::Type& _rType )
4363 Any aReturn = FmXTextCell::queryAggregation(_rType);
4365 if ( !aReturn.hasValue() )
4366 aReturn = FmXComboBoxCell_Base::queryInterface( _rType );
4368 return aReturn;
4372 Sequence< Type > SAL_CALL FmXComboBoxCell::getTypes( )
4374 return ::comphelper::concatSequences(
4375 FmXTextCell::getTypes(),
4376 FmXComboBoxCell_Base::getTypes()
4381 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXComboBoxCell )
4384 void SAL_CALL FmXComboBoxCell::addItemListener(const Reference< awt::XItemListener >& l)
4386 m_aItemListeners.addInterface( l );
4390 void SAL_CALL FmXComboBoxCell::removeItemListener(const Reference< awt::XItemListener >& l)
4392 m_aItemListeners.removeInterface( l );
4396 void SAL_CALL FmXComboBoxCell::addActionListener(const Reference< awt::XActionListener >& l)
4398 m_aActionListeners.addInterface( l );
4402 void SAL_CALL FmXComboBoxCell::removeActionListener(const Reference< awt::XActionListener >& l)
4404 m_aActionListeners.removeInterface( l );
4408 void SAL_CALL FmXComboBoxCell::addItem( const OUString& Item, sal_Int16 Pos )
4410 ::osl::MutexGuard aGuard( m_aMutex );
4411 if ( m_pComboBox )
4412 m_pComboBox->InsertEntry( Item, Pos );
4416 void SAL_CALL FmXComboBoxCell::addItems( const Sequence< OUString >& Items, sal_Int16 Pos )
4418 ::osl::MutexGuard aGuard( m_aMutex );
4419 if ( m_pComboBox )
4421 sal_uInt16 nP = Pos;
4422 for ( sal_Int32 n = 0; n < Items.getLength(); n++ )
4424 m_pComboBox->InsertEntry( Items.getConstArray()[n], nP );
4425 if ( Pos != -1 )
4426 nP++;
4432 void SAL_CALL FmXComboBoxCell::removeItems( sal_Int16 Pos, sal_Int16 Count )
4434 ::osl::MutexGuard aGuard( m_aMutex );
4435 if ( m_pComboBox )
4437 for ( sal_uInt16 n = Count; n; )
4438 m_pComboBox->RemoveEntryAt( Pos + (--n) );
4443 sal_Int16 SAL_CALL FmXComboBoxCell::getItemCount()
4445 ::osl::MutexGuard aGuard( m_aMutex );
4446 return m_pComboBox ? m_pComboBox->GetEntryCount() : 0;
4450 OUString SAL_CALL FmXComboBoxCell::getItem( sal_Int16 Pos )
4452 ::osl::MutexGuard aGuard( m_aMutex );
4453 return m_pComboBox ? OUString(m_pComboBox->GetEntry(Pos)) : OUString();
4456 Sequence< OUString > SAL_CALL FmXComboBoxCell::getItems()
4458 ::osl::MutexGuard aGuard( m_aMutex );
4460 Sequence< OUString > aItems;
4461 if ( m_pComboBox )
4463 const sal_Int32 nEntries = m_pComboBox->GetEntryCount();
4464 aItems.realloc( nEntries );
4465 OUString* pItem = aItems.getArray();
4466 for ( sal_Int32 n=0; n<nEntries; ++n, ++pItem )
4467 *pItem = m_pComboBox->GetEntry( n );
4469 return aItems;
4473 sal_Int16 SAL_CALL FmXComboBoxCell::getDropDownLineCount()
4475 ::osl::MutexGuard aGuard( m_aMutex );
4477 sal_Int16 nLines = 0;
4478 if ( m_pComboBox )
4479 nLines = m_pComboBox->GetDropDownLineCount();
4481 return nLines;
4485 void SAL_CALL FmXComboBoxCell::setDropDownLineCount(sal_Int16 nLines)
4487 ::osl::MutexGuard aGuard( m_aMutex );
4488 if ( m_pComboBox )
4489 m_pComboBox->SetDropDownLineCount( nLines );
4493 void FmXComboBoxCell::onWindowEvent( const VclEventId _nEventId, const vcl::Window& _rWindow, const void* _pEventData )
4496 switch ( _nEventId )
4498 case VclEventId::ComboboxSelect:
4500 awt::ItemEvent aEvent;
4501 aEvent.Source = *this;
4502 aEvent.Highlighted = 0;
4504 // with multiple selection 0xFFFF, otherwise the ID
4505 aEvent.Selected = ( m_pComboBox->GetSelectEntryCount() == 1 )
4506 ? m_pComboBox->GetSelectEntryPos()
4507 : 0xFFFF;
4508 m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent );
4510 break;
4512 default:
4513 FmXTextCell::onWindowEvent( _nEventId, _rWindow, _pEventData );
4514 break;
4519 FmXFilterCell::FmXFilterCell(DbGridColumn* pColumn, DbCellControl* pControl )
4520 :FmXGridCell( pColumn, pControl )
4521 ,m_aTextListeners(m_aMutex)
4524 DBG_ASSERT( dynamic_cast<const DbFilterField*>( m_pCellControl) != nullptr, "FmXFilterCell::FmXFilterCell: invalid cell control!" );
4525 static_cast< DbFilterField* >( m_pCellControl )->SetCommitHdl( LINK( this, FmXFilterCell, OnCommit ) );
4529 FmXFilterCell::~FmXFilterCell()
4531 if (!OComponentHelper::rBHelper.bDisposed)
4533 acquire();
4534 dispose();
4539 // XUnoTunnel
4541 sal_Int64 SAL_CALL FmXFilterCell::getSomething( const Sequence< sal_Int8 >& _rIdentifier )
4543 sal_Int64 nReturn(0);
4545 if ( (_rIdentifier.getLength() == 16)
4546 && (0 == memcmp( getUnoTunnelId().getConstArray(), _rIdentifier.getConstArray(), 16 ))
4549 nReturn = reinterpret_cast<sal_Int64>(this);
4552 return nReturn;
4555 namespace
4557 class theFmXFilterCellUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theFmXFilterCellUnoTunnelId > {};
4560 const Sequence<sal_Int8>& FmXFilterCell::getUnoTunnelId()
4562 return theFmXFilterCellUnoTunnelId::get().getSeq();
4566 void FmXFilterCell::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect )
4568 static_cast< DbFilterField* >( m_pCellControl )->PaintCell( rDev, rRect );
4571 // OComponentHelper
4573 void FmXFilterCell::disposing()
4575 css::lang::EventObject aEvt(*this);
4576 m_aTextListeners.disposeAndClear(aEvt);
4578 static_cast<DbFilterField*>(m_pCellControl)->SetCommitHdl(Link<DbFilterField&,void>());
4580 FmXGridCell::disposing();
4584 Any SAL_CALL FmXFilterCell::queryAggregation( const css::uno::Type& _rType )
4586 Any aReturn = FmXGridCell::queryAggregation(_rType);
4588 if ( !aReturn.hasValue() )
4589 aReturn = FmXFilterCell_Base::queryInterface( _rType );
4591 return aReturn;
4595 Sequence< css::uno::Type > SAL_CALL FmXFilterCell::getTypes( )
4597 return ::comphelper::concatSequences(
4598 FmXGridCell::getTypes(),
4599 FmXFilterCell_Base::getTypes()
4604 IMPLEMENT_GET_IMPLEMENTATION_ID( FmXFilterCell )
4606 // css::awt::XTextComponent
4608 void SAL_CALL FmXFilterCell::addTextListener(const Reference< css::awt::XTextListener >& l)
4610 m_aTextListeners.addInterface( l );
4614 void SAL_CALL FmXFilterCell::removeTextListener(const Reference< css::awt::XTextListener >& l)
4616 m_aTextListeners.removeInterface( l );
4620 void SAL_CALL FmXFilterCell::setText( const OUString& aText )
4622 ::osl::MutexGuard aGuard( m_aMutex );
4623 static_cast<DbFilterField*>(m_pCellControl)->SetText(aText);
4627 void SAL_CALL FmXFilterCell::insertText( const css::awt::Selection& /*rSel*/, const OUString& /*aText*/ )
4632 OUString SAL_CALL FmXFilterCell::getText()
4634 ::osl::MutexGuard aGuard( m_aMutex );
4635 return static_cast<DbFilterField*>(m_pCellControl)->GetText();
4639 OUString SAL_CALL FmXFilterCell::getSelectedText()
4641 return getText();
4645 void SAL_CALL FmXFilterCell::setSelection( const css::awt::Selection& /*aSelection*/ )
4650 css::awt::Selection SAL_CALL FmXFilterCell::getSelection()
4652 return css::awt::Selection();
4656 sal_Bool SAL_CALL FmXFilterCell::isEditable()
4658 return true;
4662 void SAL_CALL FmXFilterCell::setEditable( sal_Bool /*bEditable*/ )
4667 sal_Int16 SAL_CALL FmXFilterCell::getMaxTextLen()
4669 return 0;
4673 void SAL_CALL FmXFilterCell::setMaxTextLen( sal_Int16 /*nLen*/ )
4678 IMPL_LINK_NOARG(FmXFilterCell, OnCommit, DbFilterField&, void)
4680 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aTextListeners );
4681 css::awt::TextEvent aEvt;
4682 aEvt.Source = *this;
4683 while( aIt.hasMoreElements() )
4684 static_cast< css::awt::XTextListener *>(aIt.next())->textChanged( aEvt );
4687 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */