/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::connectivity; using namespace ::svxform; using namespace ::comphelper; using namespace ::svt; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::form; using namespace ::dbtools::DBTypeConversion; using namespace ::dbtools; using ::com::sun::star::util::XNumberFormatter; constexpr OUString INVALIDTEXT = u"###"_ustr; constexpr OUString OBJECTTEXT = u""_ustr; //= helper namespace { LineEnd getModelLineEndSetting( const Reference< XPropertySet >& _rxModel ) { LineEnd eFormat = LINEEND_LF; try { sal_Int16 nLineEndFormat = awt::LineEndFormat::LINE_FEED; Reference< XPropertySetInfo > xPSI; if ( _rxModel.is() ) xPSI = _rxModel->getPropertySetInfo(); OSL_ENSURE( xPSI.is(), "getModelLineEndSetting: invalid column model!" ); if ( xPSI.is() && xPSI->hasPropertyByName( FM_PROP_LINEENDFORMAT ) ) { OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_LINEENDFORMAT ) >>= nLineEndFormat ); switch ( nLineEndFormat ) { case awt::LineEndFormat::CARRIAGE_RETURN: eFormat = LINEEND_CR; break; case awt::LineEndFormat::LINE_FEED: eFormat = LINEEND_LF; break; case awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED: eFormat = LINEEND_CRLF; break; default: OSL_FAIL( "getModelLineEndSetting: what's this?" ); } } } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "svx", "getModelLineEndSetting" ); } return eFormat; } } //= DbGridColumn CellControllerRef DbGridColumn::s_xEmptyController; void DbGridColumn::CreateControl(sal_Int32 _nFieldPos, const Reference< css::beans::XPropertySet >& xField, sal_Int32 nTypeId) { Clear(); m_nTypeId = static_cast(nTypeId); if (xField != m_xField) { // initial setting m_xField = xField; xField->getPropertyValue(FM_PROP_FORMATKEY) >>= m_nFormatKey; m_nFieldPos = static_cast(_nFieldPos); m_bReadOnly = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISREADONLY)); m_bAutoValue = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_AUTOINCREMENT)); m_nFieldType = static_cast(::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE))); switch (m_nFieldType) { case DataType::DATE: case DataType::TIME: case DataType::TIMESTAMP: case DataType::BIT: case DataType::BOOLEAN: case DataType::TINYINT: case DataType::SMALLINT: case DataType::INTEGER: case DataType::BIGINT: case DataType::FLOAT: case DataType::REAL: case DataType::DOUBLE: case DataType::NUMERIC: case DataType::DECIMAL: m_nAlign = css::awt::TextAlign::RIGHT; m_bNumeric = true; break; default: m_nAlign = css::awt::TextAlign::LEFT; break; } } std::unique_ptr pCellControl; if (m_rParent.IsFilterMode()) { pCellControl.reset(new DbFilterField(m_rParent.getContext(),*this)); } else { switch (nTypeId) { case TYPE_CHECKBOX: pCellControl.reset(new DbCheckBox(*this)); break; case TYPE_COMBOBOX: pCellControl.reset(new DbComboBox(*this)); break; case TYPE_CURRENCYFIELD: pCellControl.reset(new DbCurrencyField(*this)); break; case TYPE_DATEFIELD: pCellControl.reset(new DbDateField(*this)); break; case TYPE_LISTBOX: pCellControl.reset(new DbListBox(*this)); break; case TYPE_NUMERICFIELD: pCellControl.reset(new DbNumericField(*this)); break; case TYPE_PATTERNFIELD: pCellControl.reset(new DbPatternField( *this, m_rParent.getContext() )); break; case TYPE_TEXTFIELD: pCellControl.reset(new DbTextField(*this)); break; case TYPE_TIMEFIELD: pCellControl.reset(new DbTimeField(*this)); break; case TYPE_FORMATTEDFIELD: pCellControl.reset(new DbFormattedField(*this)); break; default: OSL_FAIL("DbGridColumn::CreateControl: Unknown Column"); return; } } Reference< XRowSet > xCur; if (m_rParent.getDataSource()) xCur.set(Reference< XInterface >(*m_rParent.getDataSource()), UNO_QUERY); // TODO : the cursor wrapper should use an XRowSet interface, too pCellControl->Init( m_rParent.GetDataWindow(), xCur ); // now create the control wrapper auto pTempCellControl = pCellControl.get(); if (m_rParent.IsFilterMode()) m_pCell = new FmXFilterCell(this, std::unique_ptr(static_cast(pCellControl.release()))); else { switch (nTypeId) { case TYPE_CHECKBOX: m_pCell = new FmXCheckBoxCell( this, std::move(pCellControl) ); break; case TYPE_LISTBOX: m_pCell = new FmXListBoxCell( this, std::move(pCellControl) ); break; case TYPE_COMBOBOX: m_pCell = new FmXComboBoxCell( this, std::move(pCellControl) ); break; default: m_pCell = new FmXEditCell( this, std::move(pCellControl) ); } } m_pCell->init(); impl_toggleScriptManager_nothrow( true ); // only if we use have a bound field, we use a controller for displaying the // window in the grid if (m_xField.is()) m_xController = pTempCellControl->CreateController(); } void DbGridColumn::impl_toggleScriptManager_nothrow( bool _bAttach ) { try { Reference< container::XChild > xChild( m_xModel, UNO_QUERY_THROW ); Reference< script::XEventAttacherManager > xManager( xChild->getParent(), UNO_QUERY_THROW ); Reference< container::XIndexAccess > xContainer( xChild->getParent(), UNO_QUERY_THROW ); sal_Int32 nIndexInParent( getElementPos( xContainer, m_xModel ) ); Reference< XInterface > xCellInterface( *m_pCell, UNO_QUERY ); if ( _bAttach ) xManager->attach( nIndexInParent, xCellInterface, Any( xCellInterface ) ); else xManager->detach( nIndexInParent, xCellInterface ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } void DbGridColumn::UpdateFromField(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter) { if (FmXFilterCell* pCell = dynamic_cast(m_pCell.get())) pCell->Update(); else if (pRow && pRow->IsValid() && m_nFieldPos >= 0 && m_pCell.is() && pRow->HasField(m_nFieldPos)) { dynamic_cast(*m_pCell).UpdateFromField( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter ); } } bool DbGridColumn::Commit() { bool bResult = true; if (!m_bInSave && m_pCell.is()) { m_bInSave = true; bResult = m_pCell->Commit(); // store the data into the model FmXDataCell* pDataCell = dynamic_cast( m_pCell.get() ); if (bResult && pDataCell) { Reference< css::form::XBoundComponent > xComp(m_xModel, UNO_QUERY); if (xComp.is()) bResult = xComp->commit(); } m_bInSave = false; } return bResult; } DbGridColumn::~DbGridColumn() { Clear(); } void DbGridColumn::setModel(const css::uno::Reference< css::beans::XPropertySet >& _xModel) { if ( m_pCell.is() ) impl_toggleScriptManager_nothrow( false ); m_xModel = _xModel; if ( m_pCell.is() ) impl_toggleScriptManager_nothrow( true ); } void DbGridColumn::Clear() { if ( m_pCell.is() ) { impl_toggleScriptManager_nothrow( false ); m_pCell->dispose(); m_pCell.clear(); } m_xController = nullptr; m_xField = nullptr; m_nFormatKey = 0; m_nFieldPos = -1; m_bReadOnly = true; m_bAutoValue = false; m_nFieldType = DataType::OTHER; } sal_Int16 DbGridColumn::SetAlignment(sal_Int16 _nAlign) { if (_nAlign == -1) { // 'Standard' if (m_xField.is()) { sal_Int32 nType = 0; m_xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nType; switch (nType) { case DataType::NUMERIC: case DataType::DECIMAL: case DataType::DOUBLE: case DataType::REAL: case DataType::BIGINT: case DataType::INTEGER: case DataType::SMALLINT: case DataType::TINYINT: case DataType::DATE: case DataType::TIME: case DataType::TIMESTAMP: _nAlign = css::awt::TextAlign::RIGHT; break; case DataType::BIT: case DataType::BOOLEAN: _nAlign = css::awt::TextAlign::CENTER; break; default: _nAlign = css::awt::TextAlign::LEFT; break; } } else _nAlign = css::awt::TextAlign::LEFT; } m_nAlign = _nAlign; if (m_pCell.is() && m_pCell->isAlignedController()) m_pCell->AlignControl(m_nAlign); return m_nAlign; } sal_Int16 DbGridColumn::SetAlignmentFromModel(sal_Int16 nStandardAlign) { Any aAlign( m_xModel->getPropertyValue(FM_PROP_ALIGN)); if (aAlign.hasValue()) { sal_Int16 nTest = sal_Int16(); if (aAlign >>= nTest) nStandardAlign = nTest; } return SetAlignment(nStandardAlign); } void DbGridColumn::setLock(bool _bLock) { if (m_bLocked == _bLock) return; m_bLocked = _bLock; // is the column we represent active ? if (m_bHidden) return; // no, it isn't (or at least it shouldn't be ...) if (m_rParent.GetCurColumnId() == m_nId) { m_rParent.DeactivateCell(); m_rParent.ActivateCell(m_rParent.GetCurRow(), m_rParent.GetCurColumnId()); } } OUString DbGridColumn::GetCellText(const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter) const { OUString aText; if (m_pCell.is() && dynamic_cast( m_pCell.get() ) != nullptr) return aText; if (!pRow || !pRow->IsValid()) aText = INVALIDTEXT; else if (pRow->HasField(m_nFieldPos)) { aText = GetCellText( pRow->GetField( m_nFieldPos ).getColumn(), xFormatter ); } return aText; } OUString DbGridColumn::GetCellText(const Reference< css::sdb::XColumn >& xField, const Reference< XNumberFormatter >& xFormatter) const { OUString aText; if (xField.is()) { FmXTextCell* pTextCell = dynamic_cast( m_pCell.get() ); if (pTextCell) aText = pTextCell->GetText(xField, xFormatter); else if (m_bObject) aText = OBJECTTEXT; } return aText; } Reference< css::sdb::XColumn > DbGridColumn::GetCurrentFieldValue() const { Reference< css::sdb::XColumn > xField; const DbGridRowRef xRow = m_rParent.GetCurrentRow(); if (xRow.is() && xRow->HasField(m_nFieldPos)) { xField = xRow->GetField(m_nFieldPos).getColumn(); } return xField; } void DbGridColumn::Paint(OutputDevice& rDev, const tools::Rectangle& rRect, const DbGridRow* pRow, const Reference< XNumberFormatter >& xFormatter) { bool bEnabled = ( rDev.GetOutDevType() != OUTDEV_WINDOW ) || ( rDev.GetOwnerWindow()->IsEnabled() ); FmXDataCell* pDataCell = dynamic_cast( m_pCell.get() ); if (pDataCell) { if (!pRow || !pRow->IsValid()) { DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center; if ( !bEnabled ) nStyle |= DrawTextFlags::Disable; rDev.DrawText(rRect, INVALIDTEXT, nStyle); } else if (m_bAutoValue && pRow->IsNew()) { DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter; if ( !bEnabled ) nStyle |= DrawTextFlags::Disable; switch (GetAlignment()) { case css::awt::TextAlign::RIGHT: nStyle |= DrawTextFlags::Right; break; case css::awt::TextAlign::CENTER: nStyle |= DrawTextFlags::Center; break; default: nStyle |= DrawTextFlags::Left; } rDev.DrawText(rRect, SvxResId(RID_STR_AUTOFIELD), nStyle); } else if (pRow->HasField(m_nFieldPos)) { pDataCell->PaintFieldToCell(rDev, rRect, pRow->GetField( m_nFieldPos ).getColumn(), xFormatter); } } else if (!m_pCell.is()) { if (!pRow || !pRow->IsValid()) { DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center; if ( !bEnabled ) nStyle |= DrawTextFlags::Disable; rDev.DrawText(rRect, INVALIDTEXT, nStyle); } else if (pRow->HasField(m_nFieldPos) && m_bObject) { DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::Center; if ( !bEnabled ) nStyle |= DrawTextFlags::Disable; rDev.DrawText(rRect, OBJECTTEXT, nStyle); } } else if ( auto pFilterCell = dynamic_cast( m_pCell.get() ) ) pFilterCell->PaintCell( rDev, rRect ); } void DbGridColumn::ImplInitWindow( vcl::Window const & rParent, const InitWindowFacet _eInitWhat ) { if ( m_pCell.is() ) m_pCell->ImplInitWindow( rParent, _eInitWhat ); } //= cell controls DbCellControl::DbCellControl( DbGridColumn& _rColumn ) :OPropertyChangeListener(m_aMutex) ,m_bTransparent( false ) ,m_bAlignedController( true ) ,m_bAccessingValueProperty( false ) ,m_rColumn( _rColumn ) ,m_pPainter( nullptr ) ,m_pWindow( nullptr ) { Reference< XPropertySet > xColModelProps = _rColumn.getModel(); if ( !xColModelProps.is() ) return; // if our model's format key changes we want to propagate the new value to our windows m_pModelChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, _rColumn.getModel()); // be listener for some common properties implDoPropertyListening( FM_PROP_READONLY, false ); implDoPropertyListening( FM_PROP_ENABLED, false ); // add as listener for all known "value" properties implDoPropertyListening( FM_PROP_VALUE, false ); implDoPropertyListening( FM_PROP_STATE, false ); implDoPropertyListening( FM_PROP_TEXT, false ); implDoPropertyListening( FM_PROP_EFFECTIVE_VALUE, false ); implDoPropertyListening( FM_PROP_SELECT_SEQ, false ); implDoPropertyListening( FM_PROP_DATE, false ); implDoPropertyListening( FM_PROP_TIME, false ); // be listener at the bound field as well try { Reference< XPropertySetInfo > xPSI( xColModelProps->getPropertySetInfo(), UNO_SET_THROW ); if ( xPSI->hasPropertyByName( FM_PROP_BOUNDFIELD ) ) { Reference< XPropertySet > xField; xColModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField; if ( xField.is() ) { m_pFieldChangeBroadcaster = new ::comphelper::OPropertyChangeMultiplexer(this, xField); m_pFieldChangeBroadcaster->addProperty( FM_PROP_ISREADONLY ); } } } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "svx", "DbCellControl::doPropertyListening" ); } } void DbCellControl::implDoPropertyListening(const OUString& _rPropertyName, bool _bWarnIfNotExistent) { try { Reference< XPropertySet > xColModelProps = m_rColumn.getModel(); Reference< XPropertySetInfo > xPSI; if ( xColModelProps.is() ) xPSI = xColModelProps->getPropertySetInfo(); DBG_ASSERT( !_bWarnIfNotExistent || ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) ), "DbCellControl::doPropertyListening: no property set info or non-existent property!" ); if ( xPSI.is() && xPSI->hasPropertyByName( _rPropertyName ) ) m_pModelChangeBroadcaster->addProperty( _rPropertyName ); } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "svx", "DbCellControl::doPropertyListening" ); } } void DbCellControl::doPropertyListening(const OUString& _rPropertyName) { implDoPropertyListening( _rPropertyName, true ); } static void lcl_clearBroadCaster(rtl::Reference<::comphelper::OPropertyChangeMultiplexer>& _pBroadcaster) { if ( _pBroadcaster.is() ) { _pBroadcaster->dispose(); _pBroadcaster.clear(); // no delete, this is done implicitly } } DbCellControl::~DbCellControl() { lcl_clearBroadCaster(m_pModelChangeBroadcaster); lcl_clearBroadCaster(m_pFieldChangeBroadcaster); m_pWindow.disposeAndClear(); m_pPainter.disposeAndClear(); } void DbCellControl::implValuePropertyChanged( ) { OSL_ENSURE( !isValuePropertyLocked(), "DbCellControl::implValuePropertyChanged: not to be called with the value property locked!" ); if ( m_pWindow ) { if ( m_rColumn.getModel().is() ) updateFromModel( m_rColumn.getModel() ); } } void DbCellControl::implAdjustGenericFieldSetting( const Reference< XPropertySet >& /*_rxModel*/ ) { // nothing to do here } void DbCellControl::_propertyChanged(const PropertyChangeEvent& _rEvent) { SolarMutexGuard aGuard; Reference< XPropertySet > xSourceProps( _rEvent.Source, UNO_QUERY ); if ( _rEvent.PropertyName == FM_PROP_VALUE || _rEvent.PropertyName == FM_PROP_STATE || _rEvent.PropertyName == FM_PROP_TEXT || _rEvent.PropertyName == FM_PROP_EFFECTIVE_VALUE || _rEvent.PropertyName == FM_PROP_SELECT_SEQ || _rEvent.PropertyName == FM_PROP_DATE || _rEvent.PropertyName == FM_PROP_TIME ) { // it was one of the known "value" properties if ( !isValuePropertyLocked() ) { implValuePropertyChanged( ); } } else if ( _rEvent.PropertyName == FM_PROP_READONLY ) { implAdjustReadOnly( xSourceProps, true); } else if ( _rEvent.PropertyName == FM_PROP_ISREADONLY ) { bool bReadOnly = true; _rEvent.NewValue >>= bReadOnly; m_rColumn.SetReadOnly(bReadOnly); implAdjustReadOnly( xSourceProps, false); } else if ( _rEvent.PropertyName == FM_PROP_ENABLED ) { implAdjustEnabled( xSourceProps ); } else implAdjustGenericFieldSetting( xSourceProps ); } bool DbCellControl::Commit() { // lock the listening for value property changes lockValueProperty(); // commit the content of the control into the model's value property bool bReturn = false; try { bReturn = commitControl(); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } // unlock the listening for value property changes unlockValueProperty(); // outta here return bReturn; } void DbCellControl::ImplInitWindow( vcl::Window const & rParent, const InitWindowFacet _eInitWhat ) { svt::ControlBase* pWindows[] = { m_pPainter, m_pWindow }; if (_eInitWhat & InitWindowFacet::WritingMode) { for (svt::ControlBase* pWindow : pWindows) { if (pWindow) pWindow->EnableRTL(rParent.IsRTLEnabled()); } } if (_eInitWhat & InitWindowFacet::Font) { const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); const Fraction& rZoom = rParent.GetZoom(); for (svt::ControlBase* pWindow : pWindows) { if (!pWindow) continue; vcl::Font aFont = rStyleSettings.GetFieldFont(); aFont.SetTransparent(isTransparent()); if (rParent.IsControlFont()) aFont.Merge(rParent.GetControlFont()); if (rZoom.GetNumerator() != rZoom.GetDenominator()) { Size aSize = aFont.GetFontSize(); aSize.setWidth(std::round(double(aSize.Width() * rZoom))); aSize.setHeight(std::round(double(aSize.Height() * rZoom))); aFont.SetFontSize(aSize); } pWindow->SetPointFont(aFont); } } if ((_eInitWhat & InitWindowFacet::Font) || (_eInitWhat & InitWindowFacet::Foreground)) { Color aTextColor(rParent.IsControlForeground() ? rParent.GetControlForeground() : rParent.GetTextColor()); bool bTextLineColor = rParent.IsTextLineColor(); Color aTextLineColor(rParent.GetTextLineColor()); for (svt::ControlBase* pWindow : pWindows) { if (pWindow) { pWindow->SetTextColor(aTextColor); if (rParent.IsControlForeground()) pWindow->SetControlForeground(aTextColor); if (bTextLineColor) pWindow->SetTextLineColor(); else pWindow->SetTextLineColor(aTextLineColor); } } } if (!(_eInitWhat & InitWindowFacet::Background)) return; if (rParent.IsControlBackground()) { Color aColor(rParent.GetControlBackground()); for (svt::ControlBase* pWindow : pWindows) { if (pWindow) { if (isTransparent()) pWindow->SetBackground(); else { pWindow->SetBackground(aColor); pWindow->SetControlBackground(aColor); } pWindow->GetOutDev()->SetFillColor(aColor); } } } else { if (m_pPainter) { if (isTransparent()) m_pPainter->SetBackground(); else m_pPainter->SetBackground(rParent.GetBackground()); m_pPainter->GetOutDev()->SetFillColor(rParent.GetOutDev()->GetFillColor()); } if (m_pWindow) { if (isTransparent()) m_pWindow->SetBackground(rParent.GetBackground()); else m_pWindow->GetOutDev()->SetFillColor(rParent.GetOutDev()->GetFillColor()); } } } void DbCellControl::implAdjustReadOnly( const Reference< XPropertySet >& _rxModel,bool i_bReadOnly ) { DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustReadOnly: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustReadOnly: invalid model!" ); if ( !(m_pWindow && _rxModel.is()) ) return; bool bReadOnly = m_rColumn.IsReadOnly(); if ( !bReadOnly ) { _rxModel->getPropertyValue( i_bReadOnly ? FM_PROP_READONLY : FM_PROP_ISREADONLY) >>= bReadOnly; } m_pWindow->SetEditableReadOnly(bReadOnly); } void DbCellControl::implAdjustEnabled( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbCellControl::implAdjustEnabled: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbCellControl::implAdjustEnabled: invalid model!" ); if ( m_pWindow && _rxModel.is() ) { bool bEnable = true; _rxModel->getPropertyValue( FM_PROP_ENABLED ) >>= bEnable; m_pWindow->Enable( bEnable ); } } void DbCellControl::Init(BrowserDataWin& rParent, const Reference< XRowSet >& _rxCursor) { ImplInitWindow( rParent, InitWindowFacet::All ); if ( m_pWindow ) { // align the control if ( isAlignedController() ) AlignControl( m_rColumn.GetAlignment() ); try { // some other common properties Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW ); Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW ); if ( xModelPSI->hasPropertyByName( FM_PROP_READONLY ) ) { implAdjustReadOnly( xModel,true ); } if ( xModelPSI->hasPropertyByName( FM_PROP_ENABLED ) ) { implAdjustEnabled( xModel ); } if ( xModelPSI->hasPropertyByName( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) ) { sal_Int16 nWheelBehavior = css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY; OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) >>= nWheelBehavior ); MouseWheelBehaviour nVclSetting = MouseWheelBehaviour::FocusOnly; switch ( nWheelBehavior ) { case css::awt::MouseWheelBehavior::SCROLL_DISABLED: nVclSetting = MouseWheelBehaviour::Disable; break; case css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY: nVclSetting = MouseWheelBehaviour::FocusOnly; break; case css::awt::MouseWheelBehavior::SCROLL_ALWAYS: nVclSetting = MouseWheelBehaviour::ALWAYS; break; default: OSL_FAIL( "DbCellControl::Init: invalid MouseWheelBehavior!" ); break; } AllSettings aSettings = m_pWindow->GetSettings(); MouseSettings aMouseSettings = aSettings.GetMouseSettings(); aMouseSettings.SetWheelBehavior( nVclSetting ); aSettings.SetMouseSettings( aMouseSettings ); m_pWindow->SetSettings( aSettings, true ); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } m_xCursor = _rxCursor; if ( m_rColumn.getModel().is() ) updateFromModel( m_rColumn.getModel() ); } void DbCellControl::SetTextLineColor() { if (m_pWindow) m_pWindow->SetTextLineColor(); if (m_pPainter) m_pPainter->SetTextLineColor(); } void DbCellControl::SetTextLineColor(const Color& _rColor) { if (m_pWindow) m_pWindow->SetTextLineColor(_rColor); if (m_pPainter) m_pPainter->SetTextLineColor(_rColor); } namespace { void lcl_implAlign( vcl::Window* _pWindow, WinBits _nAlignmentBit ) { if (EditControlBase* pControl = dynamic_cast(_pWindow)) { switch (_nAlignmentBit) { case WB_LEFT: pControl->get_widget().set_alignment(TxtAlign::Left); break; case WB_CENTER: pControl->get_widget().set_alignment(TxtAlign::Center); break; case WB_RIGHT: pControl->get_widget().set_alignment(TxtAlign::Right); break; } return; } WinBits nStyle = _pWindow->GetStyle(); nStyle &= ~(WB_LEFT | WB_RIGHT | WB_CENTER); _pWindow->SetStyle( nStyle | _nAlignmentBit ); } } void DbCellControl::AlignControl(sal_Int16 nAlignment) { WinBits nAlignmentBit = 0; switch (nAlignment) { case css::awt::TextAlign::RIGHT: nAlignmentBit = WB_RIGHT; break; case css::awt::TextAlign::CENTER: nAlignmentBit = WB_CENTER; break; default: nAlignmentBit = WB_LEFT; break; } lcl_implAlign( m_pWindow, nAlignmentBit ); if ( m_pPainter ) lcl_implAlign( m_pPainter, nAlignmentBit ); } void DbCellControl::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect) { m_pPainter->SetSizePixel(rRect.GetSize()); m_pPainter->Draw(&rDev, rRect.TopLeft(), SystemTextColorFlags::NONE); } void DbCellControl::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter ) { m_pPainter->SetText( GetFormatText( _rxField, _rxFormatter ) ); PaintCell( _rDev, _rRect ); } double DbCellControl::GetValue(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) const { double fValue = 0; if (m_rColumn.IsNumeric()) { try { fValue = _rxField->getDouble(); } catch(const Exception&) { } } else { bool bSuccess = false; try { fValue = _rxField->getDouble(); bSuccess = true; } catch(const Exception&) { } if (!bSuccess) { try { fValue = xFormatter->convertStringToNumber(m_rColumn.GetKey(), _rxField->getString()); } catch(const Exception&) { } } } return fValue; } void DbCellControl::invalidatedController() { m_rColumn.GetParent().refreshController(m_rColumn.GetId(), DbGridControl::GrantControlAccess()); } // CellModels DbLimitedLengthField::DbLimitedLengthField( DbGridColumn& _rColumn ) :DbCellControl( _rColumn ) { doPropertyListening( FM_PROP_MAXTEXTLEN ); } void DbLimitedLengthField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbLimitedLengthField::implAdjustGenericFieldSetting: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbLimitedLengthField::implAdjustGenericFieldSetting: invalid model!" ); if ( m_pWindow && _rxModel.is() ) { sal_Int16 nMaxLen = 0; _rxModel->getPropertyValue( FM_PROP_MAXTEXTLEN ) >>= nMaxLen; implSetMaxTextLen( nMaxLen ); } } void DbLimitedLengthField::implSetEffectiveMaxTextLen(sal_Int32 nMaxLen) { dynamic_cast(*m_pWindow).get_widget().set_max_length(nMaxLen); if (m_pPainter) dynamic_cast(*m_pPainter).get_widget().set_max_length(nMaxLen); } DbTextField::DbTextField(DbGridColumn& _rColumn) :DbLimitedLengthField(_rColumn) ,m_bIsMultiLineEdit(false) { } DbTextField::~DbTextField( ) { m_pPainterImplementation.reset(); m_pEdit.reset(); } void DbTextField::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1); Reference< XPropertySet > xModel( m_rColumn.getModel() ); bool bLeftAlign = true; // is this a multi-line field? bool bIsMultiLine = false; try { if ( xModel.is() ) { OSL_VERIFY( xModel->getPropertyValue( FM_PROP_MULTILINE ) >>= bIsMultiLine ); } } catch( const Exception& ) { TOOLS_WARN_EXCEPTION("svx", "caught an exception while determining the multi-line capabilities!"); } m_bIsMultiLineEdit = bIsMultiLine; if ( bIsMultiLine ) { auto xEditControl = VclPtr::Create(&rParent); auto xEditPainter = VclPtr::Create(&rParent); switch (nAlignment) { case awt::TextAlign::RIGHT: xEditControl->get_widget().set_alignment(TxtAlign::Right); xEditPainter->get_widget().set_alignment(TxtAlign::Right); bLeftAlign = false; break; case awt::TextAlign::CENTER: xEditControl->get_widget().set_alignment(TxtAlign::Center); xEditPainter->get_widget().set_alignment(TxtAlign::Center); bLeftAlign = false; break; } m_pWindow = xEditControl; m_pEdit.reset(new MultiLineEditImplementation(*xEditControl)); m_pPainter = xEditPainter; m_pPainterImplementation.reset(new MultiLineEditImplementation(*xEditPainter)); } else { auto xEditControl = VclPtr::Create(&rParent); auto xEditPainter = VclPtr::Create(&rParent); switch (nAlignment) { case awt::TextAlign::RIGHT: xEditControl->get_widget().set_alignment(TxtAlign::Right); xEditPainter->get_widget().set_alignment(TxtAlign::Right); bLeftAlign = false; break; case awt::TextAlign::CENTER: xEditControl->get_widget().set_alignment(TxtAlign::Center); xEditPainter->get_widget().set_alignment(TxtAlign::Center); bLeftAlign = false; break; } m_pWindow = xEditControl; m_pEdit.reset(new EntryImplementation(*xEditControl)); m_pPainter = xEditPainter; m_pPainterImplementation.reset(new EntryImplementation(*xEditPainter)); } if (bLeftAlign) { // this is so that when getting the focus, the selection is oriented left-to-right AllSettings aSettings = m_pWindow->GetSettings(); StyleSettings aStyleSettings = aSettings.GetStyleSettings(); aStyleSettings.SetSelectionOptions( aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst); aSettings.SetStyleSettings(aStyleSettings); m_pWindow->SetSettings(aSettings); } implAdjustGenericFieldSetting( xModel ); DbLimitedLengthField::Init( rParent, xCursor ); } CellControllerRef DbTextField::CreateController() const { return new EditCellController( m_pEdit.get() ); } void DbTextField::PaintFieldToCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter ) { if ( m_pPainterImplementation ) m_pPainterImplementation->SetText( GetFormatText( _rxField, _rxFormatter ) ); DbLimitedLengthField::PaintFieldToCell( _rDev, _rRect, _rxField, _rxFormatter ); } OUString DbTextField::GetFormatText(const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, const Color** /*ppColor*/) { if (!_rxField.is()) return OUString(); const css::uno::Reference xPS(_rxField, UNO_QUERY); FormattedColumnValue fmter( xFormatter, xPS ); try { return fmter.getFormattedValue(); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } return OUString(); } void DbTextField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) { m_pEdit->SetText( GetFormatText( _rxField, xFormatter ) ); m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) ); } void DbTextField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTextField::updateFromModel: invalid call!" ); OUString sText; _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText; sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen(); if (nMaxTextLen > 0 && sText.getLength() > nMaxTextLen) { sal_Int32 nDiff = sText.getLength() - nMaxTextLen; sText = sText.replaceAt(sText.getLength() - nDiff,nDiff, u""); } m_pEdit->SetText( sText ); m_pEdit->SetSelection( Selection( SELECTION_MAX, SELECTION_MIN ) ); } bool DbTextField::commitControl() { OUString aText( m_pEdit->GetText( getModelLineEndSetting( m_rColumn.getModel() ) ) ); // we have to check if the length before we can decide if the value was modified sal_Int32 nMaxTextLen = m_pEdit->GetMaxTextLen(); if (nMaxTextLen > 0) { OUString sOldValue; m_rColumn.getModel()->getPropertyValue( FM_PROP_TEXT ) >>= sOldValue; // if the new value didn't change we must set the old long value again if ( sOldValue.getLength() > nMaxTextLen && sOldValue.compareTo(aText,nMaxTextLen) == 0 ) aText = sOldValue; } m_rColumn.getModel()->setPropertyValue( FM_PROP_TEXT, Any( aText ) ); return true; } void DbTextField::implSetEffectiveMaxTextLen( sal_Int32 _nMaxLen ) { if ( m_pEdit ) m_pEdit->SetMaxTextLen( _nMaxLen ); if ( m_pPainterImplementation ) m_pPainterImplementation->SetMaxTextLen( _nMaxLen ); } DbFormattedField::DbFormattedField(DbGridColumn& _rColumn) :DbLimitedLengthField(_rColumn) { // if our model's format key changes we want to propagate the new value to our windows doPropertyListening( FM_PROP_FORMATKEY ); } DbFormattedField::~DbFormattedField() { } void DbFormattedField::Init( BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { sal_Int16 nAlignment = m_rColumn.SetAlignmentFromModel(-1); Reference< css::beans::XPropertySet > xUnoModel = m_rColumn.getModel(); auto xEditControl = VclPtr::Create(&rParent, false); auto xEditPainter = VclPtr::Create(&rParent, false); weld::EntryFormatter& rControlFormatter = xEditControl->get_formatter(); weld::EntryFormatter& rPainterFormatter = xEditPainter->get_formatter(); m_pWindow = xEditControl.get(); m_pPainter = xEditPainter.get(); switch (nAlignment) { case awt::TextAlign::RIGHT: xEditControl->get_widget().set_alignment(TxtAlign::Right); xEditPainter->get_widget().set_alignment(TxtAlign::Right); break; case awt::TextAlign::CENTER: xEditControl->get_widget().set_alignment(TxtAlign::Center); xEditPainter->get_widget().set_alignment(TxtAlign::Center); break; default: { // Everything just so that the selection goes from right to left when getting focus SelectionOptions eOptions = rControlFormatter.GetEntrySelectionOptions(); rControlFormatter.SetEntrySelectionOptions(eOptions | SelectionOptions::ShowFirst); break; } } implAdjustGenericFieldSetting( xUnoModel ); rControlFormatter.SetStrictFormat(false); rPainterFormatter.SetStrictFormat(false); // if one allows any formatting, one cannot make an entry check anyway // (the FormattedField does not support that anyway, only derived classes) // get the formatter from the uno model // (I could theoretically also go via the css::util::NumberFormatter, which the cursor would // surely give me. The problem is that I can not really rely on the fact that the two // formatters are the same. Clean is the whole thing if I go via the UNO model.) sal_Int32 nFormatKey = -1; // let's see if the model has one ... DBG_ASSERT(::comphelper::hasProperty(FM_PROP_FORMATSSUPPLIER, xUnoModel), "DbFormattedField::Init : invalid UNO model !"); Any aSupplier( xUnoModel->getPropertyValue(FM_PROP_FORMATSSUPPLIER)); if (aSupplier.hasValue()) { m_xSupplier.set(aSupplier, css::uno::UNO_QUERY); if (m_xSupplier.is()) { // if we take the supplier from the model, then also the key Any aFmtKey( xUnoModel->getPropertyValue(FM_PROP_FORMATKEY)); if (aFmtKey.hasValue()) { DBG_ASSERT(aFmtKey.getValueType().getTypeClass() == TypeClass_LONG, "DbFormattedField::Init : invalid format key property (no sal_Int32) !"); nFormatKey = ::comphelper::getINT32(aFmtKey); } else { SAL_INFO("svx.fmcomp", "DbFormattedField::Init : my uno-model has no format-key, but a formats supplier !"); // the OFormattedModel which we usually are working with ensures that the model has a format key // as soon as the form is loaded. Unfortunally this method here is called from within loaded, too. // So if our LoadListener is called before the LoadListener of the model, this "else case" is // allowed. // Of course our property listener for the FormatKey property will notify us if the prop is changed, // so this here isn't really bad... nFormatKey = 0; } } } // No? Maybe the css::form::component::Form behind the cursor? if (!m_xSupplier.is()) { if (xCursor.is()) { // If we take the formatter from the cursor, then also the key from the field to which we are bound m_xSupplier = getNumberFormats(getConnection(xCursor)); if (m_rColumn.GetField().is()) nFormatKey = ::comphelper::getINT32(m_rColumn.GetField()->getPropertyValue(FM_PROP_FORMATKEY)); } } SvNumberFormatter* pFormatterUsed = nullptr; if (m_xSupplier.is()) { SvNumberFormatsSupplierObj* pImplementation = comphelper::getFromUnoTunnel(m_xSupplier); if (pImplementation) pFormatterUsed = pImplementation->GetNumberFormatter(); else // Everything is invalid: the supplier is of the wrong type, then we can not // rely on a standard formatter to know the (possibly non-standard) key. nFormatKey = -1; } // a standard formatter ... if (pFormatterUsed == nullptr) { pFormatterUsed = rControlFormatter.StandardFormatter(); DBG_ASSERT(pFormatterUsed != nullptr, "DbFormattedField::Init : no standard formatter given by the numeric field !"); } // ... and a standard key if (nFormatKey == -1) nFormatKey = 0; rControlFormatter.SetFormatter(pFormatterUsed); rPainterFormatter.SetFormatter(pFormatterUsed); rControlFormatter.SetFormatKey(nFormatKey); rPainterFormatter.SetFormatKey(nFormatKey); rControlFormatter.TreatAsNumber(m_rColumn.IsNumeric()); rPainterFormatter.TreatAsNumber(m_rColumn.IsNumeric()); // min and max values if (m_rColumn.IsNumeric()) { bool bClearMin = true; if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MIN, xUnoModel)) { Any aMin( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MIN)); if (aMin.getValueType().getTypeClass() != TypeClass_VOID) { DBG_ASSERT(aMin.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid min value !"); double dMin = ::comphelper::getDouble(aMin); rControlFormatter.SetMinValue(dMin); rPainterFormatter.SetMinValue(dMin); bClearMin = false; } } if (bClearMin) { rControlFormatter.ClearMinValue(); rPainterFormatter.ClearMinValue(); } bool bClearMax = true; if (::comphelper::hasProperty(FM_PROP_EFFECTIVE_MAX, xUnoModel)) { Any aMax(xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_MAX)); if (aMax.getValueType().getTypeClass() != TypeClass_VOID) { DBG_ASSERT(aMax.getValueType().getTypeClass() == TypeClass_DOUBLE, "DbFormattedField::Init : the model has an invalid max value !"); double dMax = ::comphelper::getDouble(aMax); rControlFormatter.SetMaxValue(dMax); rPainterFormatter.SetMaxValue(dMax); bClearMax = false; } } if (bClearMax) { rControlFormatter.ClearMaxValue(); rPainterFormatter.ClearMaxValue(); } } // the default value Any aDefault( xUnoModel->getPropertyValue(FM_PROP_EFFECTIVE_DEFAULT)); if (aDefault.hasValue()) { // the thing can be a double or a string switch (aDefault.getValueType().getTypeClass()) { case TypeClass_DOUBLE: if (m_rColumn.IsNumeric()) { rControlFormatter.SetDefaultValue(::comphelper::getDouble(aDefault)); rPainterFormatter.SetDefaultValue(::comphelper::getDouble(aDefault)); } else { OUString sConverted; const Color* pDummy; pFormatterUsed->GetOutputString(::comphelper::getDouble(aDefault), 0, sConverted, &pDummy); rControlFormatter.SetDefaultText(sConverted); rPainterFormatter.SetDefaultText(sConverted); } break; case TypeClass_STRING: { OUString sDefault( ::comphelper::getString(aDefault) ); if (m_rColumn.IsNumeric()) { double dVal; sal_uInt32 nTestFormat(0); if (pFormatterUsed->IsNumberFormat(sDefault, nTestFormat, dVal)) { rControlFormatter.SetDefaultValue(dVal); rPainterFormatter.SetDefaultValue(dVal); } } else { rControlFormatter.SetDefaultText(sDefault); rPainterFormatter.SetDefaultText(sDefault); } } break; default: OSL_FAIL( "DbFormattedField::Init: unexpected value type!" ); break; } } DbLimitedLengthField::Init( rParent, xCursor ); } CellControllerRef DbFormattedField::CreateController() const { return new ::svt::FormattedFieldCellController(static_cast(m_pWindow.get())); } void DbFormattedField::_propertyChanged( const PropertyChangeEvent& _rEvent ) { if (_rEvent.PropertyName == FM_PROP_FORMATKEY ) { sal_Int32 nNewKey = _rEvent.NewValue.hasValue() ? ::comphelper::getINT32(_rEvent.NewValue) : 0; DBG_ASSERT(m_pWindow && m_pPainter, "DbFormattedField::_propertyChanged : where are my windows ?"); if (m_pWindow) static_cast(m_pWindow.get())->get_formatter().SetFormatKey(nNewKey); if (m_pPainter) static_cast(m_pPainter.get())->get_formatter().SetFormatKey(nNewKey); } else { DbLimitedLengthField::_propertyChanged( _rEvent ); } } OUString DbFormattedField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** ppColor) { // no color specification by default if (ppColor != nullptr) *ppColor = nullptr; // NULL value -> empty text if (!_rxField.is()) return OUString(); FormattedControlBase* pControl = static_cast(m_pPainter.get()); weld::EntryFormatter& rPainterFormatter = pControl->get_formatter(); OUString aText; try { if (m_rColumn.IsNumeric()) { // The IsNumeric at the column says nothing about the class of the used format, but // about the class of the field bound to the column. So when you bind a FormattedField // column to a double field and format it as text, m_rColumn.IsNumeric() returns // sal_True. So that simply means that I can query the contents of the variant using // getDouble, and then I can leave the rest (the formatting) to the FormattedField. double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() ); if (_rxField->wasNull()) return aText; rPainterFormatter.SetValue(dValue); } else { // Here I can not work with a double, since the field can not provide it to me. // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form. aText = _rxField->getString(); if (_rxField->wasNull()) return aText; rPainterFormatter.SetTextFormatted(aText); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } aText = pControl->get_widget().get_text(); if (ppColor != nullptr) *ppColor = rPainterFormatter.GetLastOutputColor(); return aText; } void DbFormattedField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/) { try { FormattedControlBase* pEditControl = static_cast(m_pWindow.get()); weld::Entry& rEntry = pEditControl->get_widget(); weld::EntryFormatter& rEditFormatter = pEditControl->get_formatter(); if (!_rxField.is()) { // NULL value -> empty text rEntry.set_text(OUString()); } else if (m_rColumn.IsNumeric()) { // The IsNumeric at the column says nothing about the class of the used format, but // about the class of the field bound to the column. So when you bind a FormattedField // column to a double field and format it as text, m_rColumn.IsNumeric() returns // sal_True. So that simply means that I can query the contents of the variant using // getDouble, and then I can leave the rest (the formatting) to the FormattedField. double dValue = getValue( _rxField, m_rColumn.GetParent().getNullDate() ); if (_rxField->wasNull()) rEntry.set_text(OUString()); else rEditFormatter.SetValue(dValue); } else { // Here I can not work with a double, since the field can not provide it to me. // So simply bind the text from the css::util::NumberFormatter to the correct css::form::component::Form. OUString sText( _rxField->getString()); rEditFormatter.SetTextFormatted( sText ); rEntry.select_region(0, -1); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } void DbFormattedField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFormattedField::updateFromModel: invalid call!" ); FormattedControlBase* pEditControl = static_cast(m_pWindow.get()); weld::Entry& rEntry = pEditControl->get_widget(); weld::EntryFormatter& rEditFormatter = pEditControl->get_formatter(); OUString sText; Any aValue = _rxModel->getPropertyValue( FM_PROP_EFFECTIVE_VALUE ); if ( !aValue.hasValue() || (aValue >>= sText) ) { // our effective value is transferred as string rEditFormatter.SetTextFormatted( sText ); rEntry.select_region(0, -1); } else { double dValue = 0; aValue >>= dValue; rEditFormatter.SetValue(dValue); } } bool DbFormattedField::commitControl() { Any aNewVal; FormattedControlBase* pEditControl = static_cast(m_pWindow.get()); weld::Entry& rEntry = pEditControl->get_widget(); weld::EntryFormatter& rEditFormatter = pEditControl->get_formatter(); if (m_rColumn.IsNumeric()) { if (!rEntry.get_text().isEmpty()) aNewVal <<= rEditFormatter.GetValue(); // an empty string is passed on as void by default, to start with } else aNewVal <<= rEditFormatter.GetTextValue(); m_rColumn.getModel()->setPropertyValue(FM_PROP_EFFECTIVE_VALUE, aNewVal); return true; } DbCheckBox::DbCheckBox( DbGridColumn& _rColumn ) :DbCellControl( _rColumn ) { setAlignedController( false ); } namespace { void setCheckBoxStyle( vcl::Window* _pWindow, bool bMono ) { AllSettings aSettings = _pWindow->GetSettings(); StyleSettings aStyleSettings = aSettings.GetStyleSettings(); if( bMono ) aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::Mono ); else aStyleSettings.SetOptions( aStyleSettings.GetOptions() & (~StyleSettingsOptions::Mono) ); aSettings.SetStyleSettings( aStyleSettings ); _pWindow->SetSettings( aSettings ); } } void DbCheckBox::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { setTransparent( true ); m_pWindow = VclPtr::Create( &rParent ); m_pPainter = VclPtr::Create( &rParent ); m_pWindow->SetPaintTransparent( true ); m_pPainter->SetPaintTransparent( true ); m_pPainter->SetBackground(); try { Reference< XPropertySet > xModel( m_rColumn.getModel(), UNO_SET_THROW ); sal_Int16 nStyle = awt::VisualEffect::LOOK3D; OSL_VERIFY( xModel->getPropertyValue( FM_PROP_VISUALEFFECT ) >>= nStyle ); setCheckBoxStyle( m_pWindow, nStyle == awt::VisualEffect::FLAT ); setCheckBoxStyle( m_pPainter, nStyle == awt::VisualEffect::FLAT ); bool bTristate = true; OSL_VERIFY( xModel->getPropertyValue( FM_PROP_TRISTATE ) >>= bTristate ); static_cast< CheckBoxControl* >( m_pWindow.get() )->EnableTriState( bTristate ); static_cast< CheckBoxControl* >( m_pPainter.get() )->EnableTriState( bTristate ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } DbCellControl::Init( rParent, xCursor ); } CellControllerRef DbCheckBox::CreateController() const { return new CheckBoxCellController(static_cast(m_pWindow.get())); } static void lcl_setCheckBoxState( const Reference< css::sdb::XColumn >& _rxField, CheckBoxControl* _pCheckBoxControl ) { TriState eState = TRISTATE_INDET; if (_rxField.is()) { try { bool bValue = _rxField->getBoolean(); if (!_rxField->wasNull()) eState = bValue ? TRISTATE_TRUE : TRISTATE_FALSE; } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } _pCheckBoxControl->SetState(eState); } void DbCheckBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/) { lcl_setCheckBoxState( _rxField, static_cast(m_pWindow.get()) ); } void DbCheckBox::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect, const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) { CheckBoxControl* pControl = static_cast(m_pPainter.get()); lcl_setCheckBoxState( _rxField, pControl ); Size aBoxSize; switch (rDev.GetOutDevType()) { case OUTDEV_WINDOW: case OUTDEV_VIRDEV: aBoxSize = pControl->GetBox().get_preferred_size(); break; case OUTDEV_PRINTER: case OUTDEV_PDF: { auto nSize = std::min(rRect.GetWidth(), rRect.GetHeight()); aBoxSize = Size(nSize, nSize); break; } } tools::Rectangle aRect(Point(rRect.Left() + ((rRect.GetWidth() - aBoxSize.Width()) / 2), rRect.Top() + ((rRect.GetHeight() - aBoxSize.Height()) / 2)), aBoxSize); DbCellControl::PaintFieldToCell(rDev, aRect, _rxField, xFormatter); } void DbCheckBox::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect) { switch (rDev.GetOutDevType()) { case OUTDEV_WINDOW: case OUTDEV_VIRDEV: DbCellControl::PaintCell(rDev, rRect); break; case OUTDEV_PRINTER: case OUTDEV_PDF: { TriState eState = static_cast(m_pWindow.get())->GetState(); MapMode aResMapMode(MapUnit::Map100thMM); Size aImageSize = rDev.LogicToPixel(Size(300, 300), aResMapMode); Size aBrd1Size = rDev.LogicToPixel(Size(20, 20), aResMapMode); Size aBrd2Size = rDev.LogicToPixel(Size(30, 30), aResMapMode); int nCheckWidth = rDev.LogicToPixel(Size(20, 20), aResMapMode).Width(); tools::Rectangle aStateRect; aStateRect.SetLeft(rRect.Left() + ((rRect.GetWidth() - aImageSize.Width()) / 2)); aStateRect.SetTop(rRect.Top() + ((rRect.GetHeight() - aImageSize.Height()) / 2)); aStateRect.SetRight(aStateRect.Left() + aImageSize.Width() - 1); aStateRect.SetBottom(aStateRect.Top() + aImageSize.Height() - 1); rDev.Push(); rDev.SetMapMode(); rDev.SetLineColor(); rDev.SetFillColor(COL_BLACK); rDev.DrawRect(aStateRect); aStateRect.AdjustLeft(aBrd1Size.Width()); aStateRect.AdjustTop(aBrd1Size.Height()); aStateRect.AdjustRight(-aBrd1Size.Width()); aStateRect.AdjustBottom(-aBrd1Size.Height()); if (eState == TRISTATE_INDET) rDev.SetFillColor(COL_LIGHTGRAY); else rDev.SetFillColor(COL_WHITE); rDev.DrawRect(aStateRect); if (eState == TRISTATE_TRUE) { aStateRect.AdjustLeft(aBrd2Size.Width()); aStateRect.AdjustTop(aBrd2Size.Height()); aStateRect.AdjustRight(-aBrd2Size.Width()); aStateRect.AdjustBottom(-aBrd2Size.Height()); Point aPos11(aStateRect.TopLeft()); Point aPos12(aStateRect.BottomRight()); Point aPos21(aStateRect.TopRight()); Point aPos22(aStateRect.BottomLeft()); Point aTempPos11(aPos11); Point aTempPos12(aPos12); Point aTempPos21(aPos21); Point aTempPos22(aPos22); rDev.SetLineColor(COL_BLACK); int nDX = 0; for (int i = 0; i < nCheckWidth; i++) { if ( !(i % 2) ) { aTempPos11.setX(aPos11.X() + nDX); aTempPos12.setX(aPos12.X() + nDX); aTempPos21.setX(aPos21.X() + nDX); aTempPos22.setX(aPos22.X() + nDX); } else { nDX++; aTempPos11.setX(aPos11.X() - nDX); aTempPos12.setX(aPos12.X() - nDX); aTempPos21.setX(aPos21.X() - nDX); aTempPos22.setX(aPos22.X() - nDX); } rDev.DrawLine(aTempPos11, aTempPos12); rDev.DrawLine(aTempPos21, aTempPos22); } } rDev.Pop(); break; } } } void DbCheckBox::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCheckBox::updateFromModel: invalid call!" ); sal_Int16 nState = TRISTATE_INDET; _rxModel->getPropertyValue( FM_PROP_STATE ) >>= nState; static_cast< CheckBoxControl* >( m_pWindow.get() )->SetState( static_cast< TriState >( nState ) ); } bool DbCheckBox::commitControl() { m_rColumn.getModel()->setPropertyValue( FM_PROP_STATE, Any( static_cast( static_cast< CheckBoxControl* >( m_pWindow.get() )->GetState() ) ) ); return true; } OUString DbCheckBox::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/) { return OUString(); } DbPatternField::DbPatternField( DbGridColumn& _rColumn, const Reference& _rContext ) :DbCellControl( _rColumn ) ,m_xContext( _rContext ) { doPropertyListening( FM_PROP_LITERALMASK ); doPropertyListening( FM_PROP_EDITMASK ); doPropertyListening( FM_PROP_STRICTFORMAT ); } void DbPatternField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbPatternField::implAdjustGenericFieldSetting: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbPatternField::implAdjustGenericFieldSetting: invalid model!" ); if ( !m_pWindow || !_rxModel.is() ) return; OUString aLitMask; OUString aEditMask; bool bStrict = false; _rxModel->getPropertyValue( FM_PROP_LITERALMASK ) >>= aLitMask; _rxModel->getPropertyValue( FM_PROP_EDITMASK ) >>= aEditMask; _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) >>= bStrict; OString aAsciiEditMask(OUStringToOString(aEditMask, RTL_TEXTENCODING_ASCII_US)); weld::PatternFormatter& rEditFormatter = static_cast(m_pWindow.get())->get_formatter(); rEditFormatter.SetMask(aAsciiEditMask, aLitMask); rEditFormatter.SetStrictFormat(bStrict); weld::PatternFormatter& rPaintFormatter = static_cast(m_pPainter.get())->get_formatter(); rPaintFormatter.SetMask(aAsciiEditMask, aLitMask); rPaintFormatter.SetStrictFormat(bStrict); } void DbPatternField::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { m_rColumn.SetAlignmentFromModel(-1); m_pWindow = VclPtr::Create(&rParent); m_pPainter= VclPtr::Create(&rParent); Reference< XPropertySet > xModel( m_rColumn.getModel() ); implAdjustGenericFieldSetting( xModel ); DbCellControl::Init( rParent, xCursor ); } CellControllerRef DbPatternField::CreateController() const { return new EditCellController(static_cast(m_pWindow.get())); } OUString DbPatternField::impl_formatText( const OUString& _rText ) { weld::PatternFormatter& rPaintFormatter = static_cast(m_pPainter.get())->get_formatter(); rPaintFormatter.get_widget().set_text(_rText); rPaintFormatter.ReformatAll(); return rPaintFormatter.get_widget().get_text(); } OUString DbPatternField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/) { bool bIsForPaint = _rxField != m_rColumn.GetField(); ::std::unique_ptr< FormattedColumnValue >& rpFormatter = bIsForPaint ? m_pPaintFormatter : m_pValueFormatter; if (!rpFormatter) { rpFormatter = std::make_unique< FormattedColumnValue> ( m_xContext, getCursor(), Reference< XPropertySet >( _rxField, UNO_QUERY ) ); OSL_ENSURE(rpFormatter, "DbPatternField::Init: no value formatter!"); } else OSL_ENSURE( rpFormatter->getColumn() == _rxField, "DbPatternField::GetFormatText: my value formatter is working for another field ...!" ); // re-creating the value formatter here every time would be quite expensive ... OUString sText; if (rpFormatter) sText = rpFormatter->getFormattedValue(); return impl_formatText( sText ); } void DbPatternField::UpdateFromField( const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter ) { weld::Entry& rEntry = static_cast(m_pWindow.get())->get_widget(); rEntry.set_text(GetFormatText(_rxField, _rxFormatter)); rEntry.select_region(-1, 0); } void DbPatternField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbPatternField::updateFromModel: invalid call!" ); OUString sText; _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText; weld::Entry& rEntry = static_cast(m_pWindow.get())->get_widget(); rEntry.set_text(impl_formatText(sText)); rEntry.select_region(-1, 0); } bool DbPatternField::commitControl() { weld::Entry& rEntry = static_cast(m_pWindow.get())->get_widget(); m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, Any(rEntry.get_text())); return true; } DbSpinField::DbSpinField( DbGridColumn& _rColumn, sal_Int16 _nStandardAlign ) :DbCellControl( _rColumn ) ,m_nStandardAlign( _nStandardAlign ) { } void DbSpinField::Init(BrowserDataWin& _rParent, const Reference< XRowSet >& _rxCursor) { m_rColumn.SetAlignmentFromModel( m_nStandardAlign ); Reference< XPropertySet > xModel( m_rColumn.getModel() ); // determine if we need a spinbutton version bool bSpinButton(false); if ( ::comphelper::getBOOL( xModel->getPropertyValue( FM_PROP_SPIN ) ) ) bSpinButton = true; // create the fields m_pWindow = createField( &_rParent, bSpinButton, xModel ); m_pPainter = createField( &_rParent, bSpinButton, xModel ); // adjust all other settings which depend on the property values implAdjustGenericFieldSetting( xModel ); // call the base class DbCellControl::Init( _rParent, _rxCursor ); } CellControllerRef DbSpinField::CreateController() const { return new ::svt::FormattedFieldCellController(static_cast(m_pWindow.get())); } DbNumericField::DbNumericField( DbGridColumn& _rColumn ) :DbSpinField( _rColumn ) { doPropertyListening( FM_PROP_DECIMAL_ACCURACY ); doPropertyListening( FM_PROP_VALUEMIN ); doPropertyListening( FM_PROP_VALUEMAX ); doPropertyListening( FM_PROP_VALUESTEP ); doPropertyListening( FM_PROP_STRICTFORMAT ); doPropertyListening( FM_PROP_SHOWTHOUSANDSEP ); } void DbNumericField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbNumericField::implAdjustGenericFieldSetting: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbNumericField::implAdjustGenericFieldSetting: invalid model!" ); if ( !m_pWindow || !_rxModel.is() ) return; sal_Int32 nMin = static_cast(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) )); sal_Int32 nMax = static_cast(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) )); sal_Int32 nStep = static_cast(getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) )); bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) ); sal_Int16 nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) ); bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) ); Formatter& rEditFormatter = static_cast(m_pWindow.get())->get_formatter(); rEditFormatter.SetMinValue(nMin); rEditFormatter.SetMaxValue(nMax); rEditFormatter.SetSpinSize(nStep); rEditFormatter.SetStrictFormat(bStrict); Formatter& rPaintFormatter = static_cast(m_pPainter.get())->get_formatter(); rPaintFormatter.SetMinValue(nMin); rPaintFormatter.SetMaxValue(nMax); rPaintFormatter.SetStrictFormat(bStrict); // give a formatter to the field and the painter; // test first if I can get from the service behind a connection Reference< css::util::XNumberFormatsSupplier > xSupplier; Reference< XRowSet > xForm; if ( m_rColumn.GetParent().getDataSource() ) xForm.set( Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY ); if ( xForm.is() ) xSupplier = getNumberFormats( getConnection( xForm ), true ); SvNumberFormatter* pFormatterUsed = nullptr; if ( xSupplier.is() ) { SvNumberFormatsSupplierObj* pImplementation = comphelper::getFromUnoTunnel( xSupplier ); pFormatterUsed = pImplementation ? pImplementation->GetNumberFormatter() : nullptr; } if ( nullptr == pFormatterUsed ) { // the cursor didn't lead to success -> standard pFormatterUsed = rEditFormatter.StandardFormatter(); DBG_ASSERT( pFormatterUsed != nullptr, "DbNumericField::implAdjustGenericFieldSetting: no standard formatter given by the numeric field !" ); } rEditFormatter.SetFormatter( pFormatterUsed ); rPaintFormatter.SetFormatter( pFormatterUsed ); // and then generate a format which has the desired length after the decimal point, etc. LanguageType aAppLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType(); OUString sFormatString = pFormatterUsed->GenerateFormat(0, aAppLanguage, bThousand, false, nScale); rEditFormatter.SetFormat( sFormatString, aAppLanguage ); rPaintFormatter.SetFormat( sFormatString, aAppLanguage ); } VclPtr DbNumericField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference& /*rxModel*/) { return VclPtr::Create(pParent, bSpinButton); } namespace { OUString lcl_setFormattedNumeric_nothrow( FormattedControlBase& _rField, const DbCellControl& _rControl, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter ) { OUString sValue; if ( _rxField.is() ) { try { double fValue = _rControl.GetValue( _rxField, _rxFormatter ); if ( !_rxField->wasNull() ) { _rField.get_formatter().SetValue(fValue); sValue = _rField.get_widget().get_text(); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } return sValue; } } OUString DbNumericField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, const Color** /*ppColor*/) { return lcl_setFormattedNumeric_nothrow(dynamic_cast(*m_pPainter), *this, _rxField, _rxFormatter); } void DbNumericField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter) { lcl_setFormattedNumeric_nothrow(dynamic_cast(*m_pWindow), *this, _rxField, _rxFormatter); } void DbNumericField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbNumericField::updateFromModel: invalid call!" ); FormattedControlBase* pControl = static_cast(m_pWindow.get()); Formatter& rFormatter = pControl->get_formatter(); double dValue = 0; if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue ) rFormatter.SetValue(dValue); else { pControl->get_widget().set_text(OUString()); rFormatter.InvalidateValueState(); } } bool DbNumericField::commitControl() { FormattedControlBase* pControl = static_cast(m_pWindow.get()); OUString aText(pControl->get_widget().get_text()); Any aVal; if (!aText.isEmpty()) // not empty { Formatter& rFormatter = pControl->get_formatter(); double fValue = rFormatter.GetValue(); aVal <<= fValue; } m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal); return true; } DbCurrencyField::DbCurrencyField(DbGridColumn& _rColumn) :DbSpinField( _rColumn ) { doPropertyListening( FM_PROP_DECIMAL_ACCURACY ); doPropertyListening( FM_PROP_VALUEMIN ); doPropertyListening( FM_PROP_VALUEMAX ); doPropertyListening( FM_PROP_VALUESTEP ); doPropertyListening( FM_PROP_STRICTFORMAT ); doPropertyListening( FM_PROP_SHOWTHOUSANDSEP ); doPropertyListening( FM_PROP_CURRENCYSYMBOL ); } void DbCurrencyField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbCurrencyField::implAdjustGenericFieldSetting: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbCurrencyField::implAdjustGenericFieldSetting: invalid model!" ); if ( !m_pWindow || !_rxModel.is() ) return; sal_Int16 nScale = getINT16( _rxModel->getPropertyValue( FM_PROP_DECIMAL_ACCURACY ) ); double nMin = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMIN ) ); double nMax = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUEMAX ) ); double nStep = getDouble( _rxModel->getPropertyValue( FM_PROP_VALUESTEP ) ); bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) ); bool bThousand = getBOOL( _rxModel->getPropertyValue( FM_PROP_SHOWTHOUSANDSEP ) ); OUString aStr( getString( _rxModel->getPropertyValue(FM_PROP_CURRENCYSYMBOL ) ) ); Formatter& rEditFormatter = static_cast(m_pWindow.get())->get_formatter(); rEditFormatter.SetDecimalDigits(nScale); rEditFormatter.SetMinValue(nMin); rEditFormatter.SetMaxValue(nMax); rEditFormatter.SetSpinSize(nStep); rEditFormatter.SetStrictFormat(bStrict); weld::LongCurrencyFormatter& rCurrencyEditFormatter = static_cast(rEditFormatter); rCurrencyEditFormatter.SetUseThousandSep(bThousand); rCurrencyEditFormatter.SetCurrencySymbol(aStr); Formatter& rPaintFormatter = static_cast(m_pPainter.get())->get_formatter(); rPaintFormatter.SetDecimalDigits(nScale); rPaintFormatter.SetMinValue(nMin); rPaintFormatter.SetMaxValue(nMax); rPaintFormatter.SetStrictFormat(bStrict); weld::LongCurrencyFormatter& rPaintCurrencyFormatter = static_cast(rPaintFormatter); rPaintCurrencyFormatter.SetUseThousandSep(bThousand); rPaintCurrencyFormatter.SetCurrencySymbol(aStr); } VclPtr DbCurrencyField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference< XPropertySet >& /*rxModel*/) { return VclPtr::Create(pParent, bSpinButton); } namespace { OUString lcl_setFormattedCurrency_nothrow( FormattedControlBase& _rField, const DbCurrencyField& _rControl, const Reference< XColumn >& _rxField, const Reference< XNumberFormatter >& _rxFormatter ) { OUString sValue; if ( _rxField.is() ) { try { double fValue = _rControl.GetValue( _rxField, _rxFormatter ); if ( !_rxField->wasNull() ) { _rField.get_formatter().SetValue(fValue); sValue = _rField.get_widget().get_text(); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } return sValue; } } OUString DbCurrencyField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter, const Color** /*ppColor*/) { return lcl_setFormattedCurrency_nothrow(dynamic_cast(*m_pPainter), *this, _rxField, _rxFormatter); } void DbCurrencyField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& _rxFormatter) { lcl_setFormattedCurrency_nothrow(dynamic_cast(*m_pWindow), *this, _rxField, _rxFormatter); } void DbCurrencyField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbCurrencyField::updateFromModel: invalid call!" ); FormattedControlBase* pControl = static_cast(m_pWindow.get()); Formatter& rFormatter = pControl->get_formatter(); double dValue = 0; if ( _rxModel->getPropertyValue( FM_PROP_VALUE ) >>= dValue ) rFormatter.SetValue(dValue); else { pControl->get_widget().set_text(OUString()); rFormatter.InvalidateValueState(); } } bool DbCurrencyField::commitControl() { FormattedControlBase* pControl = static_cast(m_pWindow.get()); OUString aText(pControl->get_widget().get_text()); Any aVal; if (!aText.isEmpty()) // not empty { Formatter& rFormatter = pControl->get_formatter(); double fValue = rFormatter.GetValue(); aVal <<= fValue; } m_rColumn.getModel()->setPropertyValue(FM_PROP_VALUE, aVal); return true; } DbDateField::DbDateField( DbGridColumn& _rColumn ) :DbSpinField( _rColumn ) { doPropertyListening( FM_PROP_DATEFORMAT ); doPropertyListening( FM_PROP_DATEMIN ); doPropertyListening( FM_PROP_DATEMAX ); doPropertyListening( FM_PROP_STRICTFORMAT ); doPropertyListening( FM_PROP_DATE_SHOW_CENTURY ); } VclPtr DbDateField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference< XPropertySet >& rxModel) { // check if there is a DropDown property set to TRUE bool bDropDown = !hasProperty( FM_PROP_DROPDOWN, rxModel ) || getBOOL( rxModel->getPropertyValue( FM_PROP_DROPDOWN ) ); // given the apparent inability to set a custom up/down action for a gtk // spinbutton to have different up/down dates depending on the zone the // mouse is in, show the dropdown calendar for both the spin or dropdown case return VclPtr::Create(pParent, bSpinButton || bDropDown); } void DbDateField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbDateField::implAdjustGenericFieldSetting: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbDateField::implAdjustGenericFieldSetting: invalid model!" ); if ( !m_pWindow || !_rxModel.is() ) return; sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_DATEFORMAT ) ); util::Date aMin; OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMIN ) >>= aMin ); util::Date aMax; OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_DATEMAX ) >>= aMax ); bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) ); FormattedControlBase* pControl = static_cast(m_pWindow.get()); weld::DateFormatter& rControlFormatter = static_cast(pControl->get_formatter()); FormattedControlBase* pPainter = static_cast(m_pPainter.get()); weld::DateFormatter& rPainterFormatter = static_cast(pPainter->get_formatter()); Any aCentury = _rxModel->getPropertyValue( FM_PROP_DATE_SHOW_CENTURY ); if ( aCentury.getValueType().getTypeClass() != TypeClass_VOID ) { bool bShowDateCentury = getBOOL( aCentury ); rControlFormatter.SetShowDateCentury(bShowDateCentury); rPainterFormatter.SetShowDateCentury(bShowDateCentury); } rControlFormatter.SetExtDateFormat( static_cast(nFormat) ); rControlFormatter.SetMin( aMin ); rControlFormatter.SetMax( aMax ); rControlFormatter.SetStrictFormat( bStrict ); rControlFormatter.EnableEmptyField( true ); rPainterFormatter.SetExtDateFormat( static_cast(nFormat) ); rPainterFormatter.SetMin( aMin ); rPainterFormatter.SetMax( aMax ); rPainterFormatter.SetStrictFormat( bStrict ); rPainterFormatter.EnableEmptyField( true ); } namespace { OUString lcl_setFormattedDate_nothrow(DateControl& _rField, const Reference& _rxField) { OUString sDate; if ( _rxField.is() ) { try { css::util::Date aValue = _rxField->getDate(); if (!_rxField->wasNull()) { _rField.SetDate(::Date(aValue.Day, aValue.Month, aValue.Year)); sDate = _rField.get_widget().get_text(); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } return sDate; } } OUString DbDateField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/) { return lcl_setFormattedDate_nothrow(*static_cast(m_pPainter.get()), _rxField); } void DbDateField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/) { lcl_setFormattedDate_nothrow(*static_cast(m_pWindow.get()), _rxField); } void DbDateField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbDateField::updateFromModel: invalid call!" ); DateControl* pControl = static_cast(m_pWindow.get()); util::Date aDate; if ( _rxModel->getPropertyValue( FM_PROP_DATE ) >>= aDate ) pControl->SetDate(::Date(aDate)); else pControl->get_widget().set_text(OUString()); } bool DbDateField::commitControl() { FormattedControlBase* pControl = static_cast(m_pWindow.get()); OUString aText(pControl->get_widget().get_text()); Any aVal; if (!aText.isEmpty()) // not empty { weld::DateFormatter& rControlFormatter = static_cast(pControl->get_formatter()); aVal <<= rControlFormatter.GetDate().GetUNODate(); } m_rColumn.getModel()->setPropertyValue(FM_PROP_DATE, aVal); return true; } DbTimeField::DbTimeField( DbGridColumn& _rColumn ) :DbSpinField( _rColumn, css::awt::TextAlign::LEFT ) { doPropertyListening( FM_PROP_TIMEFORMAT ); doPropertyListening( FM_PROP_TIMEMIN ); doPropertyListening( FM_PROP_TIMEMAX ); doPropertyListening( FM_PROP_STRICTFORMAT ); } VclPtr DbTimeField::createField(BrowserDataWin* pParent, bool bSpinButton, const Reference< XPropertySet >& /*rxModel*/ ) { return VclPtr::Create(pParent, bSpinButton); } void DbTimeField::implAdjustGenericFieldSetting( const Reference< XPropertySet >& _rxModel ) { DBG_ASSERT( m_pWindow, "DbTimeField::implAdjustGenericFieldSetting: not to be called without window!" ); DBG_ASSERT( _rxModel.is(), "DbTimeField::implAdjustGenericFieldSetting: invalid model!" ); if ( !m_pWindow || !_rxModel.is() ) return; sal_Int16 nFormat = getINT16( _rxModel->getPropertyValue( FM_PROP_TIMEFORMAT ) ); util::Time aMin; OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMIN ) >>= aMin ); util::Time aMax; OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_TIMEMAX ) >>= aMax ); bool bStrict = getBOOL( _rxModel->getPropertyValue( FM_PROP_STRICTFORMAT ) ); FormattedControlBase* pControl = static_cast(m_pWindow.get()); weld::TimeFormatter& rControlFormatter = static_cast(pControl->get_formatter()); rControlFormatter.SetExtFormat(static_cast(nFormat)); rControlFormatter.SetMin(aMin); rControlFormatter.SetMax(aMax); rControlFormatter.SetStrictFormat(bStrict); rControlFormatter.EnableEmptyField(true); FormattedControlBase* pPainter = static_cast(m_pPainter.get()); weld::TimeFormatter& rPainterFormatter = static_cast(pPainter->get_formatter()); rPainterFormatter.SetExtFormat(static_cast(nFormat)); rPainterFormatter.SetMin(aMin); rPainterFormatter.SetMax(aMax); rPainterFormatter.SetStrictFormat(bStrict); rPainterFormatter.EnableEmptyField(true); } namespace { OUString lcl_setFormattedTime_nothrow(TimeControl& _rField, const Reference& _rxField) { OUString sTime; if ( _rxField.is() ) { try { css::util::Time aValue = _rxField->getTime(); if (!_rxField->wasNull()) { static_cast(_rField.get_formatter()).SetTime( ::tools::Time( aValue ) ); sTime = _rField.get_widget().get_text(); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } return sTime; } } OUString DbTimeField::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< css::util::XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/) { return lcl_setFormattedTime_nothrow(*static_cast(m_pPainter.get()), _rxField); } void DbTimeField::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/) { lcl_setFormattedTime_nothrow(*static_cast(m_pWindow.get()), _rxField); } void DbTimeField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbTimeField::updateFromModel: invalid call!" ); FormattedControlBase* pControl = static_cast(m_pWindow.get()); weld::TimeFormatter& rControlFormatter = static_cast(pControl->get_formatter()); util::Time aTime; if ( _rxModel->getPropertyValue( FM_PROP_TIME ) >>= aTime ) rControlFormatter.SetTime(::tools::Time(aTime)); else pControl->get_widget().set_text(OUString()); } bool DbTimeField::commitControl() { FormattedControlBase* pControl = static_cast(m_pWindow.get()); OUString aText(pControl->get_widget().get_text()); Any aVal; if (!aText.isEmpty()) // not empty { weld::TimeFormatter& rControlFormatter = static_cast(pControl->get_formatter()); aVal <<= rControlFormatter.GetTime().GetUNOTime(); } m_rColumn.getModel()->setPropertyValue(FM_PROP_TIME, aVal); return true; } DbComboBox::DbComboBox(DbGridColumn& _rColumn) :DbCellControl(_rColumn) { setAlignedController( false ); doPropertyListening( FM_PROP_STRINGITEMLIST ); doPropertyListening( FM_PROP_LINECOUNT ); } void DbComboBox::_propertyChanged( const PropertyChangeEvent& _rEvent ) { if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST ) { SetList(_rEvent.NewValue); } else { DbCellControl::_propertyChanged( _rEvent ) ; } } void DbComboBox::SetList(const Any& rItems) { ComboBoxControl* pField = static_cast(m_pWindow.get()); weld::ComboBox& rComboBox = pField->get_widget(); rComboBox.clear(); css::uno::Sequence aTest; if (rItems >>= aTest) { for (const OUString& rString : std::as_const(aTest)) rComboBox.append_text(rString); // tell the grid control that this controller is invalid and has to be re-initialized invalidatedController(); } } void DbComboBox::implAdjustGenericFieldSetting(const Reference&) { // we no longer pay attention to FM_PROP_LINECOUNT } void DbComboBox::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { m_rColumn.SetAlignmentFromModel(css::awt::TextAlign::LEFT); m_pWindow = VclPtr::Create( &rParent ); // selection from right to left AllSettings aSettings = m_pWindow->GetSettings(); StyleSettings aStyleSettings = aSettings.GetStyleSettings(); aStyleSettings.SetSelectionOptions( aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst); aSettings.SetStyleSettings(aStyleSettings); m_pWindow->SetSettings(aSettings, true); // some initial properties Reference< XPropertySet > xModel(m_rColumn.getModel()); SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) ); implAdjustGenericFieldSetting( xModel ); DbCellControl::Init( rParent, xCursor ); } CellControllerRef DbComboBox::CreateController() const { return new ComboBoxCellController(static_cast(m_pWindow.get())); } OUString DbComboBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter, const Color** /*ppColor*/) { const css::uno::Reference xPS(_rxField, UNO_QUERY); ::dbtools::FormattedColumnValue fmter( xFormatter, xPS ); return fmter.getFormattedValue(); } void DbComboBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) { ComboBoxControl* pControl = static_cast(m_pWindow.get()); pControl->get_widget().set_entry_text(GetFormatText(_rxField, xFormatter)); } void DbComboBox::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbComboBox::updateFromModel: invalid call!" ); OUString sText; _rxModel->getPropertyValue( FM_PROP_TEXT ) >>= sText; ComboBoxControl* pControl = static_cast(m_pWindow.get()); weld::ComboBox& rComboBox = pControl->get_widget(); OUString sOldActive = rComboBox.get_active_text(); rComboBox.set_entry_text(sText); rComboBox.select_entry_region(0, -1); if (sOldActive != rComboBox.get_active_text()) pControl->TriggerAuxModify(); } bool DbComboBox::commitControl() { ComboBoxControl* pControl = static_cast(m_pWindow.get()); weld::ComboBox& rComboBox = pControl->get_widget(); OUString aText(rComboBox.get_active_text()); m_rColumn.getModel()->setPropertyValue(FM_PROP_TEXT, Any(aText)); return true; } DbListBox::DbListBox(DbGridColumn& _rColumn) :DbCellControl(_rColumn) ,m_bBound(false) { setAlignedController( false ); doPropertyListening( FM_PROP_STRINGITEMLIST ); doPropertyListening( FM_PROP_LINECOUNT ); } void DbListBox::_propertyChanged( const css::beans::PropertyChangeEvent& _rEvent ) { if ( _rEvent.PropertyName == FM_PROP_STRINGITEMLIST ) { SetList(_rEvent.NewValue); } else { DbCellControl::_propertyChanged( _rEvent ) ; } } void DbListBox::SetList(const Any& rItems) { ListBoxControl* pField = static_cast(m_pWindow.get()); weld::ComboBox& rFieldList = pField->get_widget(); rFieldList.clear(); m_bBound = false; css::uno::Sequence aTest; if (!(rItems >>= aTest)) return; if (aTest.hasElements()) { for (const OUString& rString : std::as_const(aTest)) rFieldList.append_text(rString); m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList; m_bBound = m_aValueList.hasElements(); // tell the grid control that this controller is invalid and has to be re-initialized invalidatedController(); } } void DbListBox::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { m_rColumn.SetAlignment(css::awt::TextAlign::LEFT); m_pWindow = VclPtr::Create( &rParent ); // some initial properties Reference< XPropertySet > xModel( m_rColumn.getModel() ); SetList( xModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) ); implAdjustGenericFieldSetting( xModel ); DbCellControl::Init( rParent, xCursor ); } void DbListBox::implAdjustGenericFieldSetting( const Reference< XPropertySet >& /*rxModel*/ ) { // ignore FM_PROP_LINECOUNT } CellControllerRef DbListBox::CreateController() const { return new ListBoxCellController(static_cast(m_pWindow.get())); } OUString DbListBox::GetFormatText(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/) { OUString sText; if ( _rxField.is() ) { try { sText = _rxField->getString(); if ( m_bBound ) { sal_Int32 nPos = ::comphelper::findValue( m_aValueList, sText ); if ( nPos != -1 ) sText = static_cast(m_pWindow.get())->get_widget().get_text(nPos); else sText.clear(); } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("svx"); } } return sText; } void DbListBox::UpdateFromField(const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) { OUString sFormattedText( GetFormatText( _rxField, xFormatter ) ); weld::ComboBox& rComboBox = static_cast(m_pWindow.get())->get_widget(); if (!sFormattedText.isEmpty()) rComboBox.set_active_text(sFormattedText); else rComboBox.set_active(-1); } void DbListBox::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbListBox::updateFromModel: invalid call!" ); Sequence< sal_Int16 > aSelection; _rxModel->getPropertyValue( FM_PROP_SELECT_SEQ ) >>= aSelection; sal_Int16 nSelection = -1; if ( aSelection.hasElements() ) nSelection = aSelection[ 0 ]; ListBoxControl* pControl = static_cast(m_pWindow.get()); weld::ComboBox& rComboBox = pControl->get_widget(); int nOldActive = rComboBox.get_active(); if (nSelection >= 0 && nSelection < rComboBox.get_count()) rComboBox.set_active(nSelection); else rComboBox.set_active(-1); if (nOldActive != rComboBox.get_active()) pControl->TriggerAuxModify(); } bool DbListBox::commitControl() { Any aVal; Sequence aSelectSeq; weld::ComboBox& rComboBox = static_cast(m_pWindow.get())->get_widget(); auto nActive = rComboBox.get_active(); if (nActive != -1) { aSelectSeq.realloc(1); *aSelectSeq.getArray() = static_cast(nActive); } aVal <<= aSelectSeq; m_rColumn.getModel()->setPropertyValue(FM_PROP_SELECT_SEQ, aVal); return true; } DbFilterField::DbFilterField(const Reference< XComponentContext >& rxContext,DbGridColumn& _rColumn) :DbCellControl(_rColumn) ,OSQLParserClient(rxContext) ,m_nControlClass(css::form::FormComponentType::TEXTFIELD) ,m_bFilterList(false) ,m_bFilterListFilled(false) { setAlignedController( false ); } DbFilterField::~DbFilterField() { if (m_nControlClass == css::form::FormComponentType::CHECKBOX) static_cast(m_pWindow.get())->SetToggleHdl(Link()); } void DbFilterField::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect) { static const DrawTextFlags nStyle = DrawTextFlags::Clip | DrawTextFlags::VCenter | DrawTextFlags::Left; switch (m_nControlClass) { case FormComponentType::CHECKBOX: { // center the checkbox within the space available CheckBoxControl* pControl = static_cast(m_pPainter.get()); Size aBoxSize = pControl->GetBox().get_preferred_size(); tools::Rectangle aRect(Point(rRect.Left() + ((rRect.GetWidth() - aBoxSize.Width()) / 2), rRect.Top() + ((rRect.GetHeight() - aBoxSize.Height()) / 2)), aBoxSize); DbCellControl::PaintCell(rDev, aRect); break; } case FormComponentType::LISTBOX: rDev.DrawText(rRect, static_cast(m_pWindow.get())->get_widget().get_active_text(), nStyle); break; default: rDev.DrawText(rRect, m_aText, nStyle); } } void DbFilterField::SetList(const Any& rItems, bool bComboBox) { css::uno::Sequence aTest; rItems >>= aTest; if (!aTest.hasElements()) return; if (bComboBox) { ComboBoxControl* pField = static_cast(m_pWindow.get()); weld::ComboBox& rComboBox = pField->get_widget(); for (const OUString& rString : std::as_const(aTest)) rComboBox.append_text(rString); } else { ListBoxControl* pField = static_cast(m_pWindow.get()); weld::ComboBox& rFieldBox = pField->get_widget(); for (const OUString& rString : std::as_const(aTest)) rFieldBox.append_text(rString); m_rColumn.getModel()->getPropertyValue(FM_PROP_VALUE_SEQ) >>= m_aValueList; } } void DbFilterField::CreateControl(BrowserDataWin* pParent, const Reference< css::beans::XPropertySet >& xModel) { switch (m_nControlClass) { case css::form::FormComponentType::CHECKBOX: m_pWindow = VclPtr::Create(pParent); m_pWindow->SetPaintTransparent( true ); static_cast(m_pWindow.get())->SetToggleHdl(LINK(this, DbFilterField, OnToggle)); m_pPainter = VclPtr::Create(pParent); m_pPainter->SetPaintTransparent( true ); m_pPainter->SetBackground(); break; case css::form::FormComponentType::LISTBOX: { m_pWindow = VclPtr::Create(pParent); Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST); SetList(aItems, false); } break; case css::form::FormComponentType::COMBOBOX: { m_pWindow = VclPtr::Create(pParent); AllSettings aSettings = m_pWindow->GetSettings(); StyleSettings aStyleSettings = aSettings.GetStyleSettings(); aStyleSettings.SetSelectionOptions( aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst); aSettings.SetStyleSettings(aStyleSettings); m_pWindow->SetSettings(aSettings, true); if (!m_bFilterList) { Any aItems = xModel->getPropertyValue(FM_PROP_STRINGITEMLIST); SetList(aItems, true); } } break; default: { m_pWindow = VclPtr::Create(pParent); AllSettings aSettings = m_pWindow->GetSettings(); StyleSettings aStyleSettings = aSettings.GetStyleSettings(); aStyleSettings.SetSelectionOptions( aStyleSettings.GetSelectionOptions() | SelectionOptions::ShowFirst); aSettings.SetStyleSettings(aStyleSettings); m_pWindow->SetSettings(aSettings, true); } } } void DbFilterField::Init(BrowserDataWin& rParent, const Reference< XRowSet >& xCursor) { Reference< css::beans::XPropertySet > xModel(m_rColumn.getModel()); m_rColumn.SetAlignment(css::awt::TextAlign::LEFT); if (xModel.is()) { m_bFilterList = ::comphelper::hasProperty(FM_PROP_FILTERPROPOSAL, xModel) && ::comphelper::getBOOL(xModel->getPropertyValue(FM_PROP_FILTERPROPOSAL)); if (m_bFilterList) m_nControlClass = css::form::FormComponentType::COMBOBOX; else { sal_Int16 nClassId = ::comphelper::getINT16(xModel->getPropertyValue(FM_PROP_CLASSID)); switch (nClassId) { case FormComponentType::CHECKBOX: case FormComponentType::LISTBOX: case FormComponentType::COMBOBOX: m_nControlClass = nClassId; break; default: if (m_bFilterList) m_nControlClass = FormComponentType::COMBOBOX; else m_nControlClass = FormComponentType::TEXTFIELD; } } } CreateControl( &rParent, xModel ); DbCellControl::Init( rParent, xCursor ); // filter cells are never readonly m_pWindow->SetEditableReadOnly(false); } CellControllerRef DbFilterField::CreateController() const { CellControllerRef xController; switch (m_nControlClass) { case css::form::FormComponentType::CHECKBOX: xController = new CheckBoxCellController(static_cast(m_pWindow.get())); break; case css::form::FormComponentType::LISTBOX: xController = new ListBoxCellController(static_cast(m_pWindow.get())); break; case css::form::FormComponentType::COMBOBOX: xController = new ComboBoxCellController(static_cast(m_pWindow.get())); break; default: if (m_bFilterList) xController = new ComboBoxCellController(static_cast(m_pWindow.get())); else xController = new EditCellController(static_cast(m_pWindow.get())); } return xController; } void DbFilterField::updateFromModel( Reference< XPropertySet > _rxModel ) { OSL_ENSURE( _rxModel.is() && m_pWindow, "DbFilterField::updateFromModel: invalid call!" ); OSL_FAIL( "DbFilterField::updateFromModel: not implemented yet (how the hell did you reach this?)!" ); // TODO: implement this. // remember: updateFromModel should be some kind of opposite of commitControl } bool DbFilterField::commitControl() { OUString aText(m_aText); switch (m_nControlClass) { case css::form::FormComponentType::CHECKBOX: return true; case css::form::FormComponentType::LISTBOX: { aText.clear(); weld::ComboBox& rComboBox = static_cast(m_pWindow.get())->get_widget(); auto nActive = rComboBox.get_active(); if (nActive != -1) { sal_Int16 nPos = static_cast(nActive); if ( ( nPos >= 0 ) && ( nPos < m_aValueList.getLength() ) ) aText = m_aValueList.getConstArray()[nPos]; } if (m_aText != aText) { m_aText = aText; m_aCommitLink.Call(*this); } return true; } case css::form::FormComponentType::COMBOBOX: { aText = static_cast(m_pWindow.get())->get_widget().get_active_text(); break; } default: { aText = static_cast(m_pWindow.get())->get_widget().get_text(); break; } } if (m_aText != aText) { // check the text with the SQL-Parser OUString aNewText(comphelper::string::stripEnd(aText, ' ')); if (!aNewText.isEmpty()) { OUString aErrorMsg; Reference< XNumberFormatter > xNumberFormatter(m_rColumn.GetParent().getNumberFormatter()); std::unique_ptr< OSQLParseNode > pParseNode = predicateTree(aErrorMsg, aNewText,xNumberFormatter, m_rColumn.GetField()); if (pParseNode != nullptr) { OUString aPreparedText; css::lang::Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale(); Reference< XRowSet > xDataSourceRowSet( Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY); Reference< XConnection > xConnection(getConnection(xDataSourceRowSet)); pParseNode->parseNodeToPredicateStr(aPreparedText, xConnection, xNumberFormatter, m_rColumn.GetField(), OUString(), aAppLocale, ".", getParseContext()); m_aText = aPreparedText; } else { SQLException aError(aErrorMsg, {}, {}, 0, {}); displayException(aError, VCLUnoHelper::GetInterface(m_pWindow->GetParent())); // TODO: transport the title return false; } } else m_aText = aText; m_pWindow->SetText(m_aText); m_aCommitLink.Call(*this); } return true; } void DbFilterField::SetText(const OUString& rText) { m_aText = rText; switch (m_nControlClass) { case css::form::FormComponentType::CHECKBOX: { TriState eState; if (rText == "1") eState = TRISTATE_TRUE; else if (rText == "0") eState = TRISTATE_FALSE; else eState = TRISTATE_INDET; static_cast(m_pWindow.get())->SetState(eState); static_cast(m_pPainter.get())->SetState(eState); } break; case css::form::FormComponentType::LISTBOX: { sal_Int32 nPos = ::comphelper::findValue(m_aValueList, m_aText); static_cast(m_pWindow.get())->get_widget().set_active(nPos); } break; case css::form::FormComponentType::COMBOBOX: { static_cast(m_pWindow.get())->get_widget().set_entry_text(m_aText); break; } default: { static_cast(m_pWindow.get())->get_widget().set_text(m_aText); break; } } // now force a repaint on the window m_rColumn.GetParent().RowModified(0); } void DbFilterField::Update() { // should we fill the combobox with a filter proposal? if (!m_bFilterList || m_bFilterListFilled) return; m_bFilterListFilled = true; Reference< css::beans::XPropertySet > xField = m_rColumn.GetField(); if (!xField.is()) return; OUString aName; xField->getPropertyValue(FM_PROP_NAME) >>= aName; // the columnmodel Reference< css::container::XChild > xModelAsChild(m_rColumn.getModel(), UNO_QUERY); // the grid model xModelAsChild.set(xModelAsChild->getParent(),UNO_QUERY); Reference< XRowSet > xForm(xModelAsChild->getParent(), UNO_QUERY); if (!xForm.is()) return; Reference xFormProp(xForm,UNO_QUERY); Reference< XTablesSupplier > xSupTab; xFormProp->getPropertyValue("SingleSelectQueryComposer") >>= xSupTab; Reference< XConnection > xConnection(getConnection(xForm)); if (!xSupTab.is()) return; // search the field Reference< XColumnsSupplier > xSupCol(xSupTab,UNO_QUERY); Reference< css::container::XNameAccess > xFieldNames = xSupCol->getColumns(); if (!xFieldNames->hasByName(aName)) return; Reference< css::container::XNameAccess > xTablesNames = xSupTab->getTables(); Reference< css::beans::XPropertySet > xComposerFieldAsSet(xFieldNames->getByName(aName),UNO_QUERY); if (!xComposerFieldAsSet.is() || !::comphelper::hasProperty(FM_PROP_TABLENAME, xComposerFieldAsSet) || !::comphelper::hasProperty(FM_PROP_FIELDSOURCE, xComposerFieldAsSet)) return; OUString aFieldName; OUString aTableName; xComposerFieldAsSet->getPropertyValue(FM_PROP_FIELDSOURCE) >>= aFieldName; xComposerFieldAsSet->getPropertyValue(FM_PROP_TABLENAME) >>= aTableName; // no possibility to create a select statement // looking for the complete table name if (!xTablesNames->hasByName(aTableName)) return; // build a statement and send as query; // Access to the connection Reference< XStatement > xStatement; Reference< XResultSet > xListCursor; Reference< css::sdb::XColumn > xDataField; try { Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData(); OUString aQuote(xMeta->getIdentifierQuoteString()); OUStringBuffer aStatement("SELECT DISTINCT " + quoteName(aQuote, aName)); if (!aFieldName.isEmpty() && aName != aFieldName) { aStatement.append(" AS " + quoteName(aQuote, aFieldName)); } aStatement.append(" FROM "); Reference< XPropertySet > xTableNameAccess(xTablesNames->getByName(aTableName), UNO_QUERY_THROW); aStatement.append(composeTableNameForSelect(xConnection, xTableNameAccess)); xStatement = xConnection->createStatement(); Reference< css::beans::XPropertySet > xStatementProps(xStatement, UNO_QUERY); xStatementProps->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, Any(true)); xListCursor = xStatement->executeQuery(aStatement.makeStringAndClear()); Reference< css::sdbcx::XColumnsSupplier > xSupplyCols(xListCursor, UNO_QUERY); Reference< css::container::XIndexAccess > xFields(xSupplyCols->getColumns(), UNO_QUERY); xDataField.set(xFields->getByIndex(0), css::uno::UNO_QUERY); if (!xDataField.is()) return; } catch(const Exception&) { ::comphelper::disposeComponent(xStatement); return; } sal_Int16 i = 0; ::std::vector< OUString > aStringList; aStringList.reserve(16); OUString aStr; css::util::Date aNullDate = m_rColumn.GetParent().getNullDate(); sal_Int32 nFormatKey = m_rColumn.GetKey(); Reference< XNumberFormatter > xFormatter = m_rColumn.GetParent().getNumberFormatter(); sal_Int16 nKeyType = ::comphelper::getNumberFormatType(xFormatter->getNumberFormatsSupplier()->getNumberFormats(), nFormatKey); while (!xListCursor->isAfterLast() && i++ < SHRT_MAX) // max number of entries { aStr = getFormattedValue(xDataField, xFormatter, aNullDate, nFormatKey, nKeyType); aStringList.push_back(aStr); (void)xListCursor->next(); } ComboBoxControl* pField = static_cast(m_pWindow.get()); weld::ComboBox& rComboBox = pField->get_widget(); // filling the entries for the combobox for (const auto& rString : aStringList) rComboBox.append_text(rString); } OUString DbFilterField::GetFormatText(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/, const Color** /*ppColor*/) { return OUString(); } void DbFilterField::UpdateFromField(const Reference< XColumn >& /*_rxField*/, const Reference< XNumberFormatter >& /*xFormatter*/) { OSL_FAIL( "DbFilterField::UpdateFromField: cannot update a filter control from a field!" ); } IMPL_LINK_NOARG(DbFilterField, OnToggle, weld::CheckButton&, void) { TriState eState = static_cast(m_pWindow.get())->GetState(); OUStringBuffer aTextBuf; Reference< XRowSet > xDataSourceRowSet( Reference< XInterface >(*m_rColumn.GetParent().getDataSource()), UNO_QUERY); Reference< XConnection > xConnection(getConnection(xDataSourceRowSet)); const sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( xConnection ).getBooleanComparisonMode(); switch (eState) { case TRISTATE_TRUE: ::dbtools::getBooleanComparisonPredicate(u"", true, nBooleanComparisonMode, aTextBuf); break; case TRISTATE_FALSE: ::dbtools::getBooleanComparisonPredicate(u"", false, nBooleanComparisonMode, aTextBuf); break; case TRISTATE_INDET: break; } const OUString aText(aTextBuf.makeStringAndClear()); if (m_aText != aText) { m_aText = aText; m_aCommitLink.Call(*this); } } FmXGridCell::FmXGridCell( DbGridColumn* pColumn, std::unique_ptr _pControl ) :OComponentHelper(m_aMutex) ,m_pColumn(pColumn) ,m_pCellControl( std::move(_pControl) ) ,m_aWindowListeners( m_aMutex ) ,m_aFocusListeners( m_aMutex ) ,m_aKeyListeners( m_aMutex ) ,m_aMouseListeners( m_aMutex ) ,m_aMouseMotionListeners( m_aMutex ) { } void FmXGridCell::init() { svt::ControlBase* pEventWindow( getEventWindow() ); if ( pEventWindow ) { pEventWindow->SetFocusInHdl(LINK( this, FmXGridCell, OnFocusGained)); pEventWindow->SetFocusOutHdl(LINK( this, FmXGridCell, OnFocusLost)); pEventWindow->SetMousePressHdl(LINK( this, FmXGridCell, OnMousePress)); pEventWindow->SetMouseReleaseHdl(LINK( this, FmXGridCell, OnMouseRelease)); pEventWindow->SetMouseMoveHdl(LINK( this, FmXGridCell, OnMouseMove)); pEventWindow->SetKeyInputHdl( LINK( this, FmXGridCell, OnKeyInput) ); pEventWindow->SetKeyReleaseHdl( LINK( this, FmXGridCell, OnKeyRelease) ); } } svt::ControlBase* FmXGridCell::getEventWindow() const { if ( m_pCellControl ) return &m_pCellControl->GetWindow(); return nullptr; } FmXGridCell::~FmXGridCell() { if (!OComponentHelper::rBHelper.bDisposed) { acquire(); dispose(); } } void FmXGridCell::SetTextLineColor() { if (m_pCellControl) m_pCellControl->SetTextLineColor(); } void FmXGridCell::SetTextLineColor(const Color& _rColor) { if (m_pCellControl) m_pCellControl->SetTextLineColor(_rColor); } // XTypeProvider Sequence< Type > SAL_CALL FmXGridCell::getTypes( ) { Sequence< uno::Type > aTypes = ::comphelper::concatSequences( ::cppu::OComponentHelper::getTypes(), FmXGridCell_Base::getTypes() ); if ( m_pCellControl ) aTypes = ::comphelper::concatSequences( aTypes, FmXGridCell_WindowBase::getTypes() ); return aTypes; } IMPLEMENT_GET_IMPLEMENTATION_ID( FmXGridCell ) // OComponentHelper void FmXGridCell::disposing() { lang::EventObject aEvent( *this ); m_aWindowListeners.disposeAndClear( aEvent ); m_aFocusListeners.disposeAndClear( aEvent ); m_aKeyListeners.disposeAndClear( aEvent ); m_aMouseListeners.disposeAndClear( aEvent ); m_aMouseMotionListeners.disposeAndClear( aEvent ); OComponentHelper::disposing(); m_pColumn = nullptr; m_pCellControl.reset(); } Any SAL_CALL FmXGridCell::queryAggregation( const css::uno::Type& _rType ) { Any aReturn = OComponentHelper::queryAggregation( _rType ); if ( !aReturn.hasValue() ) aReturn = FmXGridCell_Base::queryInterface( _rType ); if ( !aReturn.hasValue() && ( m_pCellControl != nullptr ) ) aReturn = FmXGridCell_WindowBase::queryInterface( _rType ); return aReturn; } // css::awt::XControl Reference< XInterface > FmXGridCell::getContext() { return Reference< XInterface > (); } Reference< css::awt::XControlModel > FmXGridCell::getModel() { checkDisposed(OComponentHelper::rBHelper.bDisposed); return Reference< css::awt::XControlModel > (m_pColumn->getModel(), UNO_QUERY); } // css::form::XBoundControl sal_Bool FmXGridCell::getLock() { checkDisposed(OComponentHelper::rBHelper.bDisposed); return m_pColumn->isLocked(); } void FmXGridCell::setLock(sal_Bool _bLock) { checkDisposed(OComponentHelper::rBHelper.bDisposed); if (getLock() == _bLock) return; else { ::osl::MutexGuard aGuard(m_aMutex); m_pColumn->setLock(_bLock); } } void SAL_CALL FmXGridCell::setPosSize( ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int32, ::sal_Int16 ) { OSL_FAIL( "FmXGridCell::setPosSize: not implemented" ); // not allowed to tamper with this for a grid cell } awt::Rectangle SAL_CALL FmXGridCell::getPosSize( ) { OSL_FAIL( "FmXGridCell::getPosSize: not implemented" ); return awt::Rectangle(); } void SAL_CALL FmXGridCell::setVisible( sal_Bool ) { OSL_FAIL( "FmXGridCell::setVisible: not implemented" ); // not allowed to tamper with this for a grid cell } void SAL_CALL FmXGridCell::setEnable( sal_Bool ) { OSL_FAIL( "FmXGridCell::setEnable: not implemented" ); // not allowed to tamper with this for a grid cell } void SAL_CALL FmXGridCell::setFocus( ) { OSL_FAIL( "FmXGridCell::setFocus: not implemented" ); // not allowed to tamper with this for a grid cell } void SAL_CALL FmXGridCell::addWindowListener( const Reference< awt::XWindowListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aWindowListeners.addInterface( _rxListener ); } void SAL_CALL FmXGridCell::removeWindowListener( const Reference< awt::XWindowListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aWindowListeners.removeInterface( _rxListener ); } void SAL_CALL FmXGridCell::addFocusListener( const Reference< awt::XFocusListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aFocusListeners.addInterface( _rxListener ); } void SAL_CALL FmXGridCell::removeFocusListener( const Reference< awt::XFocusListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aFocusListeners.removeInterface( _rxListener ); } void SAL_CALL FmXGridCell::addKeyListener( const Reference< awt::XKeyListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aKeyListeners.addInterface( _rxListener ); } void SAL_CALL FmXGridCell::removeKeyListener( const Reference< awt::XKeyListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aKeyListeners.removeInterface( _rxListener ); } void SAL_CALL FmXGridCell::addMouseListener( const Reference< awt::XMouseListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aMouseListeners.addInterface( _rxListener ); } void SAL_CALL FmXGridCell::removeMouseListener( const Reference< awt::XMouseListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aMouseListeners.removeInterface( _rxListener ); } void SAL_CALL FmXGridCell::addMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aMouseMotionListeners.addInterface( _rxListener ); } void SAL_CALL FmXGridCell::removeMouseMotionListener( const Reference< awt::XMouseMotionListener >& _rxListener ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aMouseMotionListeners.removeInterface( _rxListener ); } void SAL_CALL FmXGridCell::addPaintListener( const Reference< awt::XPaintListener >& ) { OSL_FAIL( "FmXGridCell::addPaintListener: not implemented" ); } void SAL_CALL FmXGridCell::removePaintListener( const Reference< awt::XPaintListener >& ) { OSL_FAIL( "FmXGridCell::removePaintListener: not implemented" ); } void FmXGridCell::onFocusGained( const awt::FocusEvent& _rEvent ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aFocusListeners.notifyEach( &awt::XFocusListener::focusGained, _rEvent ); } void FmXGridCell::onFocusLost( const awt::FocusEvent& _rEvent ) { checkDisposed(OComponentHelper::rBHelper.bDisposed); m_aFocusListeners.notifyEach( &awt::XFocusListener::focusLost, _rEvent ); } IMPL_LINK_NOARG(FmXGridCell, OnFocusGained, LinkParamNone*, void) { if (!m_aFocusListeners.getLength()) return; awt::FocusEvent aEvent; aEvent.Source = *this; aEvent.Temporary = false; onFocusGained(aEvent); } IMPL_LINK_NOARG(FmXGridCell, OnFocusLost, LinkParamNone*, void) { if (!m_aFocusListeners.getLength()) return; awt::FocusEvent aEvent; aEvent.Source = *this; aEvent.Temporary = false; onFocusLost(aEvent); } IMPL_LINK(FmXGridCell, OnMousePress, const MouseEvent&, rEventData, void) { if (!m_aMouseListeners.getLength()) return; awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(rEventData, *this)); m_aMouseListeners.notifyEach(&awt::XMouseListener::mousePressed, aEvent); } IMPL_LINK(FmXGridCell, OnMouseRelease, const MouseEvent&, rEventData, void) { if (!m_aMouseListeners.getLength()) return; awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(rEventData, *this)); m_aMouseListeners.notifyEach(&awt::XMouseListener::mouseReleased, aEvent); } IMPL_LINK(FmXGridCell, OnMouseMove, const MouseEvent&, rMouseEvent, void) { if ( rMouseEvent.IsEnterWindow() || rMouseEvent.IsLeaveWindow() ) { if ( m_aMouseListeners.getLength() != 0 ) { awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) ); m_aMouseListeners.notifyEach( rMouseEvent.IsEnterWindow() ? &awt::XMouseListener::mouseEntered: &awt::XMouseListener::mouseExited, aEvent ); } } else if ( !rMouseEvent.IsEnterWindow() && !rMouseEvent.IsLeaveWindow() ) { if ( m_aMouseMotionListeners.getLength() != 0 ) { awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( rMouseEvent, *this ) ); aEvent.ClickCount = 0; const bool bSimpleMove = bool( rMouseEvent.GetMode() & MouseEventModifiers::SIMPLEMOVE ); m_aMouseMotionListeners.notifyEach( bSimpleMove ? &awt::XMouseMotionListener::mouseMoved: &awt::XMouseMotionListener::mouseDragged, aEvent ); } } } IMPL_LINK(FmXGridCell, OnKeyInput, const KeyEvent&, rEventData, void) { if (!m_aKeyListeners.getLength()) return; awt::KeyEvent aEvent(VCLUnoHelper::createKeyEvent(rEventData, *this)); m_aKeyListeners.notifyEach(&awt::XKeyListener::keyPressed, aEvent); } IMPL_LINK(FmXGridCell, OnKeyRelease, const KeyEvent&, rEventData, void) { if (!m_aKeyListeners.getLength()) return; awt::KeyEvent aEvent(VCLUnoHelper::createKeyEvent(rEventData, *this)); m_aKeyListeners.notifyEach(&awt::XKeyListener::keyReleased, aEvent); } void FmXDataCell::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect, const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) { m_pCellControl->PaintFieldToCell( rDev, rRect, _rxField, xFormatter ); } void FmXDataCell::UpdateFromColumn() { Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue()); if (xField.is()) m_pCellControl->UpdateFromField(xField, m_pColumn->GetParent().getNumberFormatter()); } FmXTextCell::FmXTextCell( DbGridColumn* pColumn, std::unique_ptr pControl ) :FmXDataCell( pColumn, std::move(pControl) ) ,m_bIsMultiLineText(false) { } void FmXTextCell::PaintFieldToCell(OutputDevice& rDev, const tools::Rectangle& rRect, const Reference< css::sdb::XColumn >& _rxField, const Reference< XNumberFormatter >& xFormatter) { DrawTextFlags nStyle = DrawTextFlags::Clip; if ( ( rDev.GetOutDevType() == OUTDEV_WINDOW ) && !rDev.GetOwnerWindow()->IsEnabled() ) nStyle |= DrawTextFlags::Disable; switch (m_pColumn->GetAlignment()) { case css::awt::TextAlign::RIGHT: nStyle |= DrawTextFlags::Right; break; case css::awt::TextAlign::CENTER: nStyle |= DrawTextFlags::Center; break; default: nStyle |= DrawTextFlags::Left; } if (!m_bIsMultiLineText) nStyle |= DrawTextFlags::VCenter; else nStyle |= DrawTextFlags::Top | DrawTextFlags::MultiLine | DrawTextFlags::WordBreak; try { const Color* pColor = nullptr; OUString aText = GetText(_rxField, xFormatter, &pColor); if (pColor != nullptr) { Color aOldTextColor( rDev.GetTextColor() ); rDev.SetTextColor( *pColor ); rDev.DrawText(rRect, aText, nStyle); rDev.SetTextColor( aOldTextColor ); } else rDev.DrawText(rRect, aText, nStyle); } catch (const Exception&) { TOOLS_WARN_EXCEPTION("svx.fmcomp", "PaintFieldToCell"); } } FmXEditCell::FmXEditCell( DbGridColumn* pColumn, std::unique_ptr pControl ) :FmXTextCell( pColumn, std::move(pControl) ) ,m_aTextListeners(m_aMutex) ,m_aChangeListeners( m_aMutex ) ,m_pEditImplementation( nullptr ) ,m_bOwnEditImplementation( false ) { DbTextField* pTextField = dynamic_cast( m_pCellControl.get() ); if ( pTextField ) { m_pEditImplementation = pTextField->GetEditImplementation(); m_bIsMultiLineText = pTextField->IsMultiLineEdit(); } else { m_pEditImplementation = new EntryImplementation(static_cast(m_pCellControl->GetWindow())); m_bOwnEditImplementation = true; } m_pEditImplementation->SetAuxModifyHdl(LINK(this, FmXEditCell, ModifyHdl)); } FmXEditCell::~FmXEditCell() { if (!OComponentHelper::rBHelper.bDisposed) { acquire(); dispose(); } } // OComponentHelper void FmXEditCell::disposing() { css::lang::EventObject aEvt(*this); m_aTextListeners.disposeAndClear(aEvt); m_aChangeListeners.disposeAndClear(aEvt); if ( m_bOwnEditImplementation ) delete m_pEditImplementation; m_pEditImplementation = nullptr; FmXDataCell::disposing(); } Any SAL_CALL FmXEditCell::queryAggregation( const css::uno::Type& _rType ) { Any aReturn = FmXTextCell::queryAggregation( _rType ); if ( !aReturn.hasValue() ) aReturn = FmXEditCell_Base::queryInterface( _rType ); return aReturn; } Sequence< css::uno::Type > SAL_CALL FmXEditCell::getTypes( ) { return ::comphelper::concatSequences( FmXTextCell::getTypes(), FmXEditCell_Base::getTypes() ); } IMPLEMENT_GET_IMPLEMENTATION_ID( FmXEditCell ) // css::awt::XTextComponent void SAL_CALL FmXEditCell::addTextListener(const Reference< css::awt::XTextListener >& l) { m_aTextListeners.addInterface( l ); } void SAL_CALL FmXEditCell::removeTextListener(const Reference< css::awt::XTextListener >& l) { m_aTextListeners.removeInterface( l ); } void SAL_CALL FmXEditCell::setText( const OUString& aText ) { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_pEditImplementation ) { m_pEditImplementation->SetText( aText ); // In Java, a textChanged is fired as well; not in VCL. // css::awt::Toolkit must be Java-compliant... onTextChanged(); } } void SAL_CALL FmXEditCell::insertText(const css::awt::Selection& rSel, const OUString& aText) { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_pEditImplementation ) { m_pEditImplementation->SetSelection( Selection( rSel.Min, rSel.Max ) ); m_pEditImplementation->ReplaceSelected( aText ); } } OUString SAL_CALL FmXEditCell::getText() { ::osl::MutexGuard aGuard( m_aMutex ); OUString aText; if ( m_pEditImplementation ) { if ( m_pEditImplementation->GetControl().IsVisible() && m_pColumn->GetParent().getDisplaySynchron()) { // if the display isn't sync with the cursor we can't ask the edit field LineEnd eLineEndFormat = getModelLineEndSetting( m_pColumn->getModel() ); aText = m_pEditImplementation->GetText( eLineEndFormat ); } else { Reference< css::sdb::XColumn > xField(m_pColumn->GetCurrentFieldValue()); if (xField.is()) aText = GetText(xField, m_pColumn->GetParent().getNumberFormatter()); } } return aText; } OUString SAL_CALL FmXEditCell::getSelectedText() { ::osl::MutexGuard aGuard( m_aMutex ); OUString aText; if ( m_pEditImplementation ) { LineEnd eLineEndFormat = m_pColumn ? getModelLineEndSetting( m_pColumn->getModel() ) : LINEEND_LF; aText = m_pEditImplementation->GetSelected( eLineEndFormat ); } return aText; } void SAL_CALL FmXEditCell::setSelection( const css::awt::Selection& aSelection ) { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_pEditImplementation ) m_pEditImplementation->SetSelection( Selection( aSelection.Min, aSelection.Max ) ); } css::awt::Selection SAL_CALL FmXEditCell::getSelection() { ::osl::MutexGuard aGuard( m_aMutex ); Selection aSel; if ( m_pEditImplementation ) aSel = m_pEditImplementation->GetSelection(); return css::awt::Selection(aSel.Min(), aSel.Max()); } sal_Bool SAL_CALL FmXEditCell::isEditable() { ::osl::MutexGuard aGuard( m_aMutex ); return m_pEditImplementation && !m_pEditImplementation->IsReadOnly() && m_pEditImplementation->GetControl().IsEnabled(); } void SAL_CALL FmXEditCell::setEditable( sal_Bool bEditable ) { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_pEditImplementation ) m_pEditImplementation->SetReadOnly( !bEditable ); } sal_Int16 SAL_CALL FmXEditCell::getMaxTextLen() { ::osl::MutexGuard aGuard( m_aMutex ); return m_pEditImplementation ? m_pEditImplementation->GetMaxTextLen() : 0; } void SAL_CALL FmXEditCell::setMaxTextLen( sal_Int16 nLen ) { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_pEditImplementation ) m_pEditImplementation->SetMaxTextLen( nLen ); } void SAL_CALL FmXEditCell::addChangeListener( const Reference< form::XChangeListener >& Listener ) { m_aChangeListeners.addInterface( Listener ); } void SAL_CALL FmXEditCell::removeChangeListener( const Reference< form::XChangeListener >& Listener ) { m_aChangeListeners.removeInterface( Listener ); } void FmXEditCell::onTextChanged() { css::awt::TextEvent aEvent; aEvent.Source = *this; m_aTextListeners.notifyEach( &awt::XTextListener::textChanged, aEvent ); } void FmXEditCell::onFocusGained( const awt::FocusEvent& _rEvent ) { FmXTextCell::onFocusGained( _rEvent ); m_sValueOnEnter = getText(); } void FmXEditCell::onFocusLost( const awt::FocusEvent& _rEvent ) { FmXTextCell::onFocusLost( _rEvent ); if ( getText() != m_sValueOnEnter ) { lang::EventObject aEvent( *this ); m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvent ); } } IMPL_LINK_NOARG(FmXEditCell, ModifyHdl, LinkParamNone*, void) { if (m_aTextListeners.getLength()) onTextChanged(); } FmXCheckBoxCell::FmXCheckBoxCell( DbGridColumn* pColumn, std::unique_ptr pControl ) :FmXDataCell( pColumn, std::move(pControl) ) ,m_aItemListeners(m_aMutex) ,m_aActionListeners( m_aMutex ) ,m_pBox( & static_cast< CheckBoxControl& >( m_pCellControl->GetWindow() ) ) { m_pBox->SetAuxModifyHdl(LINK(this, FmXCheckBoxCell, ModifyHdl)); } FmXCheckBoxCell::~FmXCheckBoxCell() { if (!OComponentHelper::rBHelper.bDisposed) { acquire(); dispose(); } } // OComponentHelper void FmXCheckBoxCell::disposing() { css::lang::EventObject aEvt(*this); m_aItemListeners.disposeAndClear(aEvt); m_aActionListeners.disposeAndClear(aEvt); m_pBox->SetToggleHdl(Link()); m_pBox = nullptr; FmXDataCell::disposing(); } Any SAL_CALL FmXCheckBoxCell::queryAggregation( const css::uno::Type& _rType ) { Any aReturn = FmXDataCell::queryAggregation( _rType ); if ( !aReturn.hasValue() ) aReturn = FmXCheckBoxCell_Base::queryInterface( _rType ); return aReturn; } Sequence< css::uno::Type > SAL_CALL FmXCheckBoxCell::getTypes( ) { return ::comphelper::concatSequences( FmXDataCell::getTypes(), FmXCheckBoxCell_Base::getTypes() ); } IMPLEMENT_GET_IMPLEMENTATION_ID( FmXCheckBoxCell ) void SAL_CALL FmXCheckBoxCell::addItemListener( const Reference< css::awt::XItemListener >& l ) { m_aItemListeners.addInterface( l ); } void SAL_CALL FmXCheckBoxCell::removeItemListener( const Reference< css::awt::XItemListener >& l ) { m_aItemListeners.removeInterface( l ); } void SAL_CALL FmXCheckBoxCell::setState( sal_Int16 n ) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { UpdateFromColumn(); m_pBox->SetState( static_cast(n) ); } } sal_Int16 SAL_CALL FmXCheckBoxCell::getState() { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { UpdateFromColumn(); return static_cast(m_pBox->GetState()); } return TRISTATE_INDET; } void SAL_CALL FmXCheckBoxCell::enableTriState(sal_Bool b) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) m_pBox->EnableTriState( b ); } void SAL_CALL FmXCheckBoxCell::addActionListener( const Reference< awt::XActionListener >& Listener ) { m_aActionListeners.addInterface( Listener ); } void SAL_CALL FmXCheckBoxCell::removeActionListener( const Reference< awt::XActionListener >& Listener ) { m_aActionListeners.removeInterface( Listener ); } void SAL_CALL FmXCheckBoxCell::setLabel( const OUString& Label ) { SolarMutexGuard aGuard; if ( m_pColumn ) { DbGridControl& rGrid( m_pColumn->GetParent() ); rGrid.SetColumnTitle( rGrid.GetColumnId( m_pColumn->GetFieldPos() ), Label ); } } void SAL_CALL FmXCheckBoxCell::setActionCommand( const OUString& Command ) { m_aActionCommand = Command; } IMPL_LINK_NOARG(FmXCheckBoxCell, ModifyHdl, LinkParamNone*, void) { // check boxes are to be committed immediately (this holds for ordinary check box controls in // documents, and this must hold for check boxes in grid columns, too // 91210 - 22.08.2001 - frank.schoenheit@sun.com m_pCellControl->Commit(); Reference< XWindow > xKeepAlive( this ); if ( m_aItemListeners.getLength() && m_pBox ) { awt::ItemEvent aEvent; aEvent.Source = *this; aEvent.Highlighted = 0; aEvent.Selected = m_pBox->GetState(); m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent ); } if ( m_aActionListeners.getLength() ) { awt::ActionEvent aEvent; aEvent.Source = *this; aEvent.ActionCommand = m_aActionCommand; m_aActionListeners.notifyEach( &awt::XActionListener::actionPerformed, aEvent ); } } FmXListBoxCell::FmXListBoxCell(DbGridColumn* pColumn, std::unique_ptr pControl) : FmXTextCell(pColumn, std::move(pControl)) , m_aItemListeners(m_aMutex) , m_aActionListeners(m_aMutex) , m_pBox(&static_cast(m_pCellControl->GetWindow())) , m_nLines(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount()) , m_bMulti(false) { m_pBox->SetAuxModifyHdl(LINK(this, FmXListBoxCell, ChangedHdl)); } FmXListBoxCell::~FmXListBoxCell() { if (!OComponentHelper::rBHelper.bDisposed) { acquire(); dispose(); } } // OComponentHelper void FmXListBoxCell::disposing() { css::lang::EventObject aEvt(*this); m_aItemListeners.disposeAndClear(aEvt); m_aActionListeners.disposeAndClear(aEvt); m_pBox->SetAuxModifyHdl(Link()); m_pBox = nullptr; FmXTextCell::disposing(); } Any SAL_CALL FmXListBoxCell::queryAggregation( const css::uno::Type& _rType ) { Any aReturn = FmXTextCell::queryAggregation(_rType); if ( !aReturn.hasValue() ) aReturn = FmXListBoxCell_Base::queryInterface( _rType ); return aReturn; } Sequence< css::uno::Type > SAL_CALL FmXListBoxCell::getTypes( ) { return ::comphelper::concatSequences( FmXTextCell::getTypes(), FmXListBoxCell_Base::getTypes() ); } IMPLEMENT_GET_IMPLEMENTATION_ID( FmXListBoxCell ) void SAL_CALL FmXListBoxCell::addItemListener(const Reference< css::awt::XItemListener >& l) { m_aItemListeners.addInterface( l ); } void SAL_CALL FmXListBoxCell::removeItemListener(const Reference< css::awt::XItemListener >& l) { m_aItemListeners.removeInterface( l ); } void SAL_CALL FmXListBoxCell::addActionListener(const Reference< css::awt::XActionListener >& l) { m_aActionListeners.addInterface( l ); } void SAL_CALL FmXListBoxCell::removeActionListener(const Reference< css::awt::XActionListener >& l) { m_aActionListeners.removeInterface( l ); } void SAL_CALL FmXListBoxCell::addItem(const OUString& aItem, sal_Int16 nPos) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { weld::ComboBox& rBox = m_pBox->get_widget(); rBox.insert_text(nPos, aItem); } } void SAL_CALL FmXListBoxCell::addItems(const css::uno::Sequence& aItems, sal_Int16 nPos) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { weld::ComboBox& rBox = m_pBox->get_widget(); sal_uInt16 nP = nPos; for ( const auto& rItem : aItems ) { rBox.insert_text(nP, rItem); if ( nPos != -1 ) // Not if 0xFFFF, because LIST_APPEND nP++; } } } void SAL_CALL FmXListBoxCell::removeItems(sal_Int16 nPos, sal_Int16 nCount) { ::osl::MutexGuard aGuard( m_aMutex ); if ( m_pBox ) { weld::ComboBox& rBox = m_pBox->get_widget(); for ( sal_uInt16 n = nCount; n; ) rBox.remove( nPos + (--n) ); } } sal_Int16 SAL_CALL FmXListBoxCell::getItemCount() { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pBox) return 0; weld::ComboBox& rBox = m_pBox->get_widget(); return rBox.get_count(); } OUString SAL_CALL FmXListBoxCell::getItem(sal_Int16 nPos) { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pBox) return OUString(); weld::ComboBox& rBox = m_pBox->get_widget(); return rBox.get_text(nPos); } css::uno::Sequence SAL_CALL FmXListBoxCell::getItems() { ::osl::MutexGuard aGuard( m_aMutex ); css::uno::Sequence aSeq; if (m_pBox) { weld::ComboBox& rBox = m_pBox->get_widget(); const sal_Int32 nEntries = rBox.get_count(); aSeq = css::uno::Sequence( nEntries ); for ( sal_Int32 n = nEntries; n; ) { --n; aSeq.getArray()[n] = rBox.get_text( n ); } } return aSeq; } sal_Int16 SAL_CALL FmXListBoxCell::getSelectedItemPos() { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { UpdateFromColumn(); weld::ComboBox& rBox = m_pBox->get_widget(); sal_Int32 nPos = rBox.get_active(); if (nPos > SHRT_MAX || nPos < SHRT_MIN) throw std::out_of_range("awt::XListBox::getSelectedItemPos can only return a short"); return nPos; } return 0; } Sequence< sal_Int16 > SAL_CALL FmXListBoxCell::getSelectedItemsPos() { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { UpdateFromColumn(); weld::ComboBox& rBox = m_pBox->get_widget(); auto nActive = rBox.get_active(); if (nActive != -1) { return { o3tl::narrowing(nActive) }; } } return {}; } OUString SAL_CALL FmXListBoxCell::getSelectedItem() { ::osl::MutexGuard aGuard( m_aMutex ); OUString aItem; if (m_pBox) { UpdateFromColumn(); weld::ComboBox& rBox = m_pBox->get_widget(); aItem = rBox.get_active_text(); } return aItem; } css::uno::Sequence SAL_CALL FmXListBoxCell::getSelectedItems() { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { UpdateFromColumn(); weld::ComboBox& rBox = m_pBox->get_widget(); auto nActive = rBox.get_active(); if (nActive != -1) { return { rBox.get_text(nActive) }; } } return {}; } void SAL_CALL FmXListBoxCell::selectItemPos(sal_Int16 nPos, sal_Bool bSelect) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { weld::ComboBox& rBox = m_pBox->get_widget(); if (bSelect) rBox.set_active(nPos); else if (nPos == rBox.get_active()) rBox.set_active(-1); } } void SAL_CALL FmXListBoxCell::selectItemsPos(const Sequence< sal_Int16 >& aPositions, sal_Bool bSelect) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { weld::ComboBox& rBox = m_pBox->get_widget(); for ( sal_uInt16 n = static_cast(aPositions.getLength()); n; ) { auto nPos = static_cast(aPositions.getConstArray()[--n]); if (bSelect) rBox.set_active(nPos); else if (nPos == rBox.get_active()) rBox.set_active(-1); } } } void SAL_CALL FmXListBoxCell::selectItem(const OUString& aItem, sal_Bool bSelect) { ::osl::MutexGuard aGuard( m_aMutex ); if (m_pBox) { weld::ComboBox& rBox = m_pBox->get_widget(); auto nPos = rBox.find_text(aItem); if (bSelect) rBox.set_active(nPos); else if (nPos == rBox.get_active()) rBox.set_active(-1); } } sal_Bool SAL_CALL FmXListBoxCell::isMutipleMode() { ::osl::MutexGuard aGuard( m_aMutex ); return m_bMulti; } void SAL_CALL FmXListBoxCell::setMultipleMode(sal_Bool bMulti) { ::osl::MutexGuard aGuard( m_aMutex ); m_bMulti = bMulti; } sal_Int16 SAL_CALL FmXListBoxCell::getDropDownLineCount() { ::osl::MutexGuard aGuard( m_aMutex ); return m_nLines; } void SAL_CALL FmXListBoxCell::setDropDownLineCount(sal_Int16 nLines) { ::osl::MutexGuard aGuard( m_aMutex ); m_nLines = nLines; // just store it to return it } void SAL_CALL FmXListBoxCell::makeVisible(sal_Int16 /*nEntry*/) { } IMPL_LINK(FmXListBoxCell, ChangedHdl, bool, bInteractive, void) { if (!m_pBox) return; weld::ComboBox& rBox = m_pBox->get_widget(); if (bInteractive && !rBox.changed_by_direct_pick()) return; OnDoubleClick(); css::awt::ItemEvent aEvent; aEvent.Source = *this; aEvent.Highlighted = 0; // with multiple selection 0xFFFF, otherwise the ID aEvent.Selected = (rBox.get_active() != -1 ) ? rBox.get_active() : 0xFFFF; m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent ); } void FmXListBoxCell::OnDoubleClick() { css::awt::ActionEvent aEvent; aEvent.Source = *this; weld::ComboBox& rBox = m_pBox->get_widget(); aEvent.ActionCommand = rBox.get_active_text(); m_aActionListeners.notifyEach( &css::awt::XActionListener::actionPerformed, aEvent ); } FmXComboBoxCell::FmXComboBoxCell( DbGridColumn* pColumn, std::unique_ptr pControl ) :FmXTextCell( pColumn, std::move(pControl) ) ,m_aItemListeners( m_aMutex ) ,m_aActionListeners( m_aMutex ) ,m_pComboBox(&static_cast(m_pCellControl->GetWindow())) ,m_nLines(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount()) { m_pComboBox->SetAuxModifyHdl(LINK(this, FmXComboBoxCell, ChangedHdl)); } FmXComboBoxCell::~FmXComboBoxCell() { if ( !OComponentHelper::rBHelper.bDisposed ) { acquire(); dispose(); } } void FmXComboBoxCell::disposing() { css::lang::EventObject aEvt(*this); m_aItemListeners.disposeAndClear(aEvt); m_aActionListeners.disposeAndClear(aEvt); m_pComboBox->SetAuxModifyHdl(Link()); m_pComboBox = nullptr; FmXTextCell::disposing(); } Any SAL_CALL FmXComboBoxCell::queryAggregation( const css::uno::Type& _rType ) { Any aReturn = FmXTextCell::queryAggregation(_rType); if ( !aReturn.hasValue() ) aReturn = FmXComboBoxCell_Base::queryInterface( _rType ); return aReturn; } Sequence< Type > SAL_CALL FmXComboBoxCell::getTypes( ) { return ::comphelper::concatSequences( FmXTextCell::getTypes(), FmXComboBoxCell_Base::getTypes() ); } IMPLEMENT_GET_IMPLEMENTATION_ID( FmXComboBoxCell ) void SAL_CALL FmXComboBoxCell::addItemListener(const Reference< awt::XItemListener >& l) { m_aItemListeners.addInterface( l ); } void SAL_CALL FmXComboBoxCell::removeItemListener(const Reference< awt::XItemListener >& l) { m_aItemListeners.removeInterface( l ); } void SAL_CALL FmXComboBoxCell::addActionListener(const Reference< awt::XActionListener >& l) { m_aActionListeners.addInterface( l ); } void SAL_CALL FmXComboBoxCell::removeActionListener(const Reference< awt::XActionListener >& l) { m_aActionListeners.removeInterface( l ); } void SAL_CALL FmXComboBoxCell::addItem( const OUString& Item, sal_Int16 Pos ) { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pComboBox) return; weld::ComboBox& rBox = m_pComboBox->get_widget(); rBox.insert_text(Pos, Item); } void SAL_CALL FmXComboBoxCell::addItems( const Sequence< OUString >& Items, sal_Int16 Pos ) { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pComboBox) return; weld::ComboBox& rBox = m_pComboBox->get_widget(); sal_uInt16 nP = Pos; for ( const auto& rItem : Items ) { rBox.insert_text(nP, rItem); if ( Pos != -1 ) nP++; } } void SAL_CALL FmXComboBoxCell::removeItems( sal_Int16 Pos, sal_Int16 Count ) { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pComboBox) return; weld::ComboBox& rBox = m_pComboBox->get_widget(); for ( sal_uInt16 n = Count; n; ) rBox.remove( Pos + (--n) ); } sal_Int16 SAL_CALL FmXComboBoxCell::getItemCount() { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pComboBox) return 0; weld::ComboBox& rBox = m_pComboBox->get_widget(); return rBox.get_count(); } OUString SAL_CALL FmXComboBoxCell::getItem( sal_Int16 Pos ) { ::osl::MutexGuard aGuard( m_aMutex ); if (!m_pComboBox) return OUString(); weld::ComboBox& rBox = m_pComboBox->get_widget(); return rBox.get_text(Pos); } Sequence< OUString > SAL_CALL FmXComboBoxCell::getItems() { ::osl::MutexGuard aGuard( m_aMutex ); Sequence< OUString > aItems; if (m_pComboBox) { weld::ComboBox& rBox = m_pComboBox->get_widget(); const sal_Int32 nEntries = rBox.get_count(); aItems.realloc( nEntries ); OUString* pItem = aItems.getArray(); for ( sal_Int32 n=0; nget_widget(); if (bInteractive && !rComboBox.changed_by_direct_pick()) return; awt::ItemEvent aEvent; aEvent.Source = *this; aEvent.Highlighted = 0; // with invalid selection 0xFFFF, otherwise the position aEvent.Selected = ( rComboBox.get_active() != -1 ) ? rComboBox.get_active() : 0xFFFF; m_aItemListeners.notifyEach( &awt::XItemListener::itemStateChanged, aEvent ); } FmXFilterCell::FmXFilterCell(DbGridColumn* pColumn, std::unique_ptr pControl ) :FmXGridCell( pColumn, std::move(pControl) ) ,m_aTextListeners(m_aMutex) { static_cast(m_pCellControl.get())->SetCommitHdl( LINK( this, FmXFilterCell, OnCommit ) ); } FmXFilterCell::~FmXFilterCell() { if (!OComponentHelper::rBHelper.bDisposed) { acquire(); dispose(); } } void FmXFilterCell::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect ) { static_cast< DbFilterField* >( m_pCellControl.get() )->PaintCell( rDev, rRect ); } // OComponentHelper void FmXFilterCell::disposing() { css::lang::EventObject aEvt(*this); m_aTextListeners.disposeAndClear(aEvt); static_cast(m_pCellControl.get())->SetCommitHdl(Link()); FmXGridCell::disposing(); } Any SAL_CALL FmXFilterCell::queryAggregation( const css::uno::Type& _rType ) { Any aReturn = FmXGridCell::queryAggregation(_rType); if ( !aReturn.hasValue() ) aReturn = FmXFilterCell_Base::queryInterface( _rType ); return aReturn; } Sequence< css::uno::Type > SAL_CALL FmXFilterCell::getTypes( ) { return ::comphelper::concatSequences( FmXGridCell::getTypes(), FmXFilterCell_Base::getTypes() ); } IMPLEMENT_GET_IMPLEMENTATION_ID( FmXFilterCell ) // css::awt::XTextComponent void SAL_CALL FmXFilterCell::addTextListener(const Reference< css::awt::XTextListener >& l) { m_aTextListeners.addInterface( l ); } void SAL_CALL FmXFilterCell::removeTextListener(const Reference< css::awt::XTextListener >& l) { m_aTextListeners.removeInterface( l ); } void SAL_CALL FmXFilterCell::setText( const OUString& aText ) { ::osl::MutexGuard aGuard( m_aMutex ); static_cast(m_pCellControl.get())->SetText(aText); } void SAL_CALL FmXFilterCell::insertText( const css::awt::Selection& /*rSel*/, const OUString& /*aText*/ ) { } OUString SAL_CALL FmXFilterCell::getText() { ::osl::MutexGuard aGuard( m_aMutex ); return static_cast(m_pCellControl.get())->GetText(); } OUString SAL_CALL FmXFilterCell::getSelectedText() { return getText(); } void SAL_CALL FmXFilterCell::setSelection( const css::awt::Selection& /*aSelection*/ ) { } css::awt::Selection SAL_CALL FmXFilterCell::getSelection() { return css::awt::Selection(); } sal_Bool SAL_CALL FmXFilterCell::isEditable() { return true; } void SAL_CALL FmXFilterCell::setEditable( sal_Bool /*bEditable*/ ) { } sal_Int16 SAL_CALL FmXFilterCell::getMaxTextLen() { return 0; } void SAL_CALL FmXFilterCell::setMaxTextLen( sal_Int16 /*nLen*/ ) { } IMPL_LINK_NOARG(FmXFilterCell, OnCommit, DbFilterField&, void) { css::awt::TextEvent aEvt; aEvt.Source = *this; m_aTextListeners.notifyEach( &css::awt::XTextListener::textChanged, aEvt ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */