1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_extensions.hxx" 26*b1cdbd2cSJim Jagielski #include "handlerhelper.hxx" 27*b1cdbd2cSJim Jagielski #ifndef EXTENSIONS_PROPRESID_HRC 28*b1cdbd2cSJim Jagielski #include "propresid.hrc" 29*b1cdbd2cSJim Jagielski #endif 30*b1cdbd2cSJim Jagielski #include "formresid.hrc" 31*b1cdbd2cSJim Jagielski #include <comphelper/extract.hxx> 32*b1cdbd2cSJim Jagielski #ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_ 33*b1cdbd2cSJim Jagielski #include "modulepcr.hxx" 34*b1cdbd2cSJim Jagielski #endif 35*b1cdbd2cSJim Jagielski #include "enumrepresentation.hxx" 36*b1cdbd2cSJim Jagielski #include "formmetadata.hxx" 37*b1cdbd2cSJim Jagielski #include "pcrcomponentcontext.hxx" 38*b1cdbd2cSJim Jagielski 39*b1cdbd2cSJim Jagielski /** === begin UNO includes === **/ 40*b1cdbd2cSJim Jagielski #include "com/sun/star/inspection/StringRepresentation.hpp" 41*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/PropertyAttribute.hpp> 42*b1cdbd2cSJim Jagielski #include <com/sun/star/uno/XComponentContext.hpp> 43*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XModifiable.hpp> 44*b1cdbd2cSJim Jagielski #include <com/sun/star/awt/XWindow.hpp> 45*b1cdbd2cSJim Jagielski #include <com/sun/star/inspection/LineDescriptor.hpp> 46*b1cdbd2cSJim Jagielski #include <com/sun/star/inspection/PropertyControlType.hpp> 47*b1cdbd2cSJim Jagielski #include <com/sun/star/inspection/XStringListControl.hpp> 48*b1cdbd2cSJim Jagielski #include <com/sun/star/inspection/XNumericControl.hpp> 49*b1cdbd2cSJim Jagielski /** === end UNO includes === **/ 50*b1cdbd2cSJim Jagielski #include <tools/debug.hxx> 51*b1cdbd2cSJim Jagielski #include <tools/diagnose_ex.h> 52*b1cdbd2cSJim Jagielski #include <tools/StringListResource.hxx> 53*b1cdbd2cSJim Jagielski #include <toolkit/helper/vclunohelper.hxx> 54*b1cdbd2cSJim Jagielski 55*b1cdbd2cSJim Jagielski #include <algorithm> 56*b1cdbd2cSJim Jagielski 57*b1cdbd2cSJim Jagielski //........................................................................ 58*b1cdbd2cSJim Jagielski namespace pcr 59*b1cdbd2cSJim Jagielski { 60*b1cdbd2cSJim Jagielski //........................................................................ 61*b1cdbd2cSJim Jagielski 62*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::uno; 63*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::lang; 64*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::awt; 65*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::util; 66*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::beans; 67*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::script; 68*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::inspection; 69*b1cdbd2cSJim Jagielski 70*b1cdbd2cSJim Jagielski //==================================================================== 71*b1cdbd2cSJim Jagielski //= PropertyHandlerHelper 72*b1cdbd2cSJim Jagielski //==================================================================== 73*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- describePropertyLine(const Property & _rProperty,LineDescriptor & _out_rDescriptor,const Reference<XPropertyControlFactory> & _rxControlFactory)74*b1cdbd2cSJim Jagielski void PropertyHandlerHelper::describePropertyLine( const Property& _rProperty, 75*b1cdbd2cSJim Jagielski LineDescriptor& /* [out] */ _out_rDescriptor, const Reference< XPropertyControlFactory >& _rxControlFactory ) 76*b1cdbd2cSJim Jagielski { 77*b1cdbd2cSJim Jagielski // display the pure property name - no L10N 78*b1cdbd2cSJim Jagielski _out_rDescriptor.DisplayName = _rProperty.Name; 79*b1cdbd2cSJim Jagielski 80*b1cdbd2cSJim Jagielski OSL_PRECOND( _rxControlFactory.is(), "PropertyHandlerHelper::describePropertyLine: no factory -> no control!" ); 81*b1cdbd2cSJim Jagielski if ( !_rxControlFactory.is() ) 82*b1cdbd2cSJim Jagielski return; 83*b1cdbd2cSJim Jagielski 84*b1cdbd2cSJim Jagielski sal_Bool bReadOnlyControl = requiresReadOnlyControl( _rProperty.Attributes ); 85*b1cdbd2cSJim Jagielski 86*b1cdbd2cSJim Jagielski // special handling for booleans (this will become a list) 87*b1cdbd2cSJim Jagielski if ( _rProperty.Type.getTypeClass() == TypeClass_BOOLEAN ) 88*b1cdbd2cSJim Jagielski { 89*b1cdbd2cSJim Jagielski ::std::vector< ::rtl::OUString > aListEntries; 90*b1cdbd2cSJim Jagielski tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries); 91*b1cdbd2cSJim Jagielski _out_rDescriptor.Control = createListBoxControl( _rxControlFactory, aListEntries, bReadOnlyControl, sal_False ); 92*b1cdbd2cSJim Jagielski return; 93*b1cdbd2cSJim Jagielski } 94*b1cdbd2cSJim Jagielski 95*b1cdbd2cSJim Jagielski sal_Int16 nControlType = PropertyControlType::TextField; 96*b1cdbd2cSJim Jagielski switch ( _rProperty.Type.getTypeClass() ) 97*b1cdbd2cSJim Jagielski { 98*b1cdbd2cSJim Jagielski case TypeClass_BYTE: 99*b1cdbd2cSJim Jagielski case TypeClass_SHORT: 100*b1cdbd2cSJim Jagielski case TypeClass_UNSIGNED_SHORT: 101*b1cdbd2cSJim Jagielski case TypeClass_LONG: 102*b1cdbd2cSJim Jagielski case TypeClass_UNSIGNED_LONG: 103*b1cdbd2cSJim Jagielski case TypeClass_HYPER: 104*b1cdbd2cSJim Jagielski case TypeClass_UNSIGNED_HYPER: 105*b1cdbd2cSJim Jagielski case TypeClass_FLOAT: 106*b1cdbd2cSJim Jagielski case TypeClass_DOUBLE: 107*b1cdbd2cSJim Jagielski nControlType = PropertyControlType::NumericField; 108*b1cdbd2cSJim Jagielski break; 109*b1cdbd2cSJim Jagielski 110*b1cdbd2cSJim Jagielski case TypeClass_SEQUENCE: 111*b1cdbd2cSJim Jagielski nControlType = PropertyControlType::StringListField; 112*b1cdbd2cSJim Jagielski break; 113*b1cdbd2cSJim Jagielski 114*b1cdbd2cSJim Jagielski default: 115*b1cdbd2cSJim Jagielski DBG_ERROR( "PropertyHandlerHelper::describePropertyLine: don't know how to represent this at the UI!" ); 116*b1cdbd2cSJim Jagielski // NO break! 117*b1cdbd2cSJim Jagielski 118*b1cdbd2cSJim Jagielski case TypeClass_STRING: 119*b1cdbd2cSJim Jagielski nControlType = PropertyControlType::TextField; 120*b1cdbd2cSJim Jagielski break; 121*b1cdbd2cSJim Jagielski } 122*b1cdbd2cSJim Jagielski 123*b1cdbd2cSJim Jagielski // create a control 124*b1cdbd2cSJim Jagielski _out_rDescriptor.Control = _rxControlFactory->createPropertyControl( nControlType, bReadOnlyControl ); 125*b1cdbd2cSJim Jagielski } 126*b1cdbd2cSJim Jagielski 127*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- 128*b1cdbd2cSJim Jagielski namespace 129*b1cdbd2cSJim Jagielski { lcl_implCreateListLikeControl(const Reference<XPropertyControlFactory> & _rxControlFactory,const::std::vector<::rtl::OUString> & _rInitialListEntries,sal_Bool _bReadOnlyControl,sal_Bool _bSorted,sal_Bool _bTrueIfListBoxFalseIfComboBox)130*b1cdbd2cSJim Jagielski Reference< XPropertyControl > lcl_implCreateListLikeControl( 131*b1cdbd2cSJim Jagielski const Reference< XPropertyControlFactory >& _rxControlFactory, 132*b1cdbd2cSJim Jagielski const ::std::vector< ::rtl::OUString >& _rInitialListEntries, 133*b1cdbd2cSJim Jagielski sal_Bool _bReadOnlyControl, 134*b1cdbd2cSJim Jagielski sal_Bool _bSorted, 135*b1cdbd2cSJim Jagielski sal_Bool _bTrueIfListBoxFalseIfComboBox 136*b1cdbd2cSJim Jagielski ) 137*b1cdbd2cSJim Jagielski { 138*b1cdbd2cSJim Jagielski Reference< XStringListControl > xListControl( 139*b1cdbd2cSJim Jagielski _rxControlFactory->createPropertyControl( 140*b1cdbd2cSJim Jagielski _bTrueIfListBoxFalseIfComboBox ? PropertyControlType::ListBox : PropertyControlType::ComboBox, _bReadOnlyControl 141*b1cdbd2cSJim Jagielski ), 142*b1cdbd2cSJim Jagielski UNO_QUERY_THROW 143*b1cdbd2cSJim Jagielski ); 144*b1cdbd2cSJim Jagielski 145*b1cdbd2cSJim Jagielski ::std::vector< ::rtl::OUString > aInitialEntries( _rInitialListEntries ); 146*b1cdbd2cSJim Jagielski if ( _bSorted ) 147*b1cdbd2cSJim Jagielski ::std::sort( aInitialEntries.begin(), aInitialEntries.end() ); 148*b1cdbd2cSJim Jagielski 149*b1cdbd2cSJim Jagielski for ( ::std::vector< ::rtl::OUString >::const_iterator loop = aInitialEntries.begin(); 150*b1cdbd2cSJim Jagielski loop != aInitialEntries.end(); 151*b1cdbd2cSJim Jagielski ++loop 152*b1cdbd2cSJim Jagielski ) 153*b1cdbd2cSJim Jagielski xListControl->appendListEntry( *loop ); 154*b1cdbd2cSJim Jagielski return xListControl.get(); 155*b1cdbd2cSJim Jagielski } 156*b1cdbd2cSJim Jagielski } 157*b1cdbd2cSJim Jagielski 158*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- createListBoxControl(const Reference<XPropertyControlFactory> & _rxControlFactory,const::std::vector<::rtl::OUString> & _rInitialListEntries,sal_Bool _bReadOnlyControl,sal_Bool _bSorted)159*b1cdbd2cSJim Jagielski Reference< XPropertyControl > PropertyHandlerHelper::createListBoxControl( const Reference< XPropertyControlFactory >& _rxControlFactory, 160*b1cdbd2cSJim Jagielski const ::std::vector< ::rtl::OUString >& _rInitialListEntries, sal_Bool _bReadOnlyControl, sal_Bool _bSorted ) 161*b1cdbd2cSJim Jagielski { 162*b1cdbd2cSJim Jagielski return lcl_implCreateListLikeControl( _rxControlFactory, _rInitialListEntries, _bReadOnlyControl, _bSorted, sal_True ); 163*b1cdbd2cSJim Jagielski } 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- createComboBoxControl(const Reference<XPropertyControlFactory> & _rxControlFactory,const::std::vector<::rtl::OUString> & _rInitialListEntries,sal_Bool _bReadOnlyControl,sal_Bool _bSorted)166*b1cdbd2cSJim Jagielski Reference< XPropertyControl > PropertyHandlerHelper::createComboBoxControl( const Reference< XPropertyControlFactory >& _rxControlFactory, 167*b1cdbd2cSJim Jagielski const ::std::vector< ::rtl::OUString >& _rInitialListEntries, sal_Bool _bReadOnlyControl, sal_Bool _bSorted ) 168*b1cdbd2cSJim Jagielski { 169*b1cdbd2cSJim Jagielski return lcl_implCreateListLikeControl( _rxControlFactory, _rInitialListEntries, _bReadOnlyControl, _bSorted, sal_False ); 170*b1cdbd2cSJim Jagielski } 171*b1cdbd2cSJim Jagielski 172*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- createNumericControl(const Reference<XPropertyControlFactory> & _rxControlFactory,sal_Int16 _nDigits,const Optional<double> & _rMinValue,const Optional<double> & _rMaxValue,sal_Bool _bReadOnlyControl)173*b1cdbd2cSJim Jagielski Reference< XPropertyControl > PropertyHandlerHelper::createNumericControl( const Reference< XPropertyControlFactory >& _rxControlFactory, 174*b1cdbd2cSJim Jagielski sal_Int16 _nDigits, const Optional< double >& _rMinValue, const Optional< double >& _rMaxValue, sal_Bool _bReadOnlyControl ) 175*b1cdbd2cSJim Jagielski { 176*b1cdbd2cSJim Jagielski Reference< XNumericControl > xNumericControl( 177*b1cdbd2cSJim Jagielski _rxControlFactory->createPropertyControl( PropertyControlType::NumericField, _bReadOnlyControl ), 178*b1cdbd2cSJim Jagielski UNO_QUERY_THROW 179*b1cdbd2cSJim Jagielski ); 180*b1cdbd2cSJim Jagielski 181*b1cdbd2cSJim Jagielski xNumericControl->setDecimalDigits( _nDigits ); 182*b1cdbd2cSJim Jagielski xNumericControl->setMinValue( _rMinValue ); 183*b1cdbd2cSJim Jagielski xNumericControl->setMaxValue( _rMaxValue ); 184*b1cdbd2cSJim Jagielski 185*b1cdbd2cSJim Jagielski return xNumericControl.get(); 186*b1cdbd2cSJim Jagielski } 187*b1cdbd2cSJim Jagielski 188*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- convertToPropertyValue(const Reference<XComponentContext> & _rxContext,const Reference<XTypeConverter> & _rxTypeConverter,const Property & _rProperty,const Any & _rControlValue)189*b1cdbd2cSJim Jagielski Any PropertyHandlerHelper::convertToPropertyValue( const Reference< XComponentContext >& _rxContext,const Reference< XTypeConverter >& _rxTypeConverter, 190*b1cdbd2cSJim Jagielski const Property& _rProperty, const Any& _rControlValue ) 191*b1cdbd2cSJim Jagielski { 192*b1cdbd2cSJim Jagielski Any aPropertyValue( _rControlValue ); 193*b1cdbd2cSJim Jagielski if ( !aPropertyValue.hasValue() ) 194*b1cdbd2cSJim Jagielski // NULL is converted to NULL 195*b1cdbd2cSJim Jagielski return aPropertyValue; 196*b1cdbd2cSJim Jagielski 197*b1cdbd2cSJim Jagielski if ( aPropertyValue.getValueType().equals( _rProperty.Type ) ) 198*b1cdbd2cSJim Jagielski // nothing to do, type is already as desired 199*b1cdbd2cSJim Jagielski return aPropertyValue; 200*b1cdbd2cSJim Jagielski 201*b1cdbd2cSJim Jagielski if ( _rControlValue.getValueType().getTypeClass() == TypeClass_STRING ) 202*b1cdbd2cSJim Jagielski { 203*b1cdbd2cSJim Jagielski ::rtl::OUString sControlValue; 204*b1cdbd2cSJim Jagielski _rControlValue >>= sControlValue; 205*b1cdbd2cSJim Jagielski 206*b1cdbd2cSJim Jagielski Reference< XStringRepresentation > xConversionHelper = StringRepresentation::create( _rxContext,_rxTypeConverter ); 207*b1cdbd2cSJim Jagielski aPropertyValue = xConversionHelper->convertToPropertyValue( sControlValue, _rProperty.Type ); 208*b1cdbd2cSJim Jagielski } 209*b1cdbd2cSJim Jagielski else 210*b1cdbd2cSJim Jagielski { 211*b1cdbd2cSJim Jagielski try 212*b1cdbd2cSJim Jagielski { 213*b1cdbd2cSJim Jagielski if ( _rxTypeConverter.is() ) 214*b1cdbd2cSJim Jagielski aPropertyValue = _rxTypeConverter->convertTo( _rControlValue, _rProperty.Type ); 215*b1cdbd2cSJim Jagielski } 216*b1cdbd2cSJim Jagielski catch( const Exception& ) 217*b1cdbd2cSJim Jagielski { 218*b1cdbd2cSJim Jagielski OSL_ENSURE( sal_False, "PropertyHandlerHelper::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); 219*b1cdbd2cSJim Jagielski } 220*b1cdbd2cSJim Jagielski } 221*b1cdbd2cSJim Jagielski 222*b1cdbd2cSJim Jagielski return aPropertyValue; 223*b1cdbd2cSJim Jagielski } 224*b1cdbd2cSJim Jagielski 225*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- convertToControlValue(const Reference<XComponentContext> & _rxContext,const Reference<XTypeConverter> & _rxTypeConverter,const Any & _rPropertyValue,const Type & _rControlValueType)226*b1cdbd2cSJim Jagielski Any PropertyHandlerHelper::convertToControlValue( const Reference< XComponentContext >& _rxContext,const Reference< XTypeConverter >& _rxTypeConverter, 227*b1cdbd2cSJim Jagielski const Any& _rPropertyValue, const Type& _rControlValueType ) 228*b1cdbd2cSJim Jagielski { 229*b1cdbd2cSJim Jagielski Any aControlValue( _rPropertyValue ); 230*b1cdbd2cSJim Jagielski if ( !aControlValue.hasValue() ) 231*b1cdbd2cSJim Jagielski // NULL is converted to NULL 232*b1cdbd2cSJim Jagielski return aControlValue; 233*b1cdbd2cSJim Jagielski 234*b1cdbd2cSJim Jagielski if ( _rControlValueType.getTypeClass() == TypeClass_STRING ) 235*b1cdbd2cSJim Jagielski { 236*b1cdbd2cSJim Jagielski Reference< XStringRepresentation > xConversionHelper = StringRepresentation::create( _rxContext,_rxTypeConverter ); 237*b1cdbd2cSJim Jagielski aControlValue <<= xConversionHelper->convertToControlValue( _rPropertyValue ); 238*b1cdbd2cSJim Jagielski } 239*b1cdbd2cSJim Jagielski else 240*b1cdbd2cSJim Jagielski { 241*b1cdbd2cSJim Jagielski try 242*b1cdbd2cSJim Jagielski { 243*b1cdbd2cSJim Jagielski if ( _rxTypeConverter.is() ) 244*b1cdbd2cSJim Jagielski aControlValue = _rxTypeConverter->convertTo( _rPropertyValue, _rControlValueType ); 245*b1cdbd2cSJim Jagielski } 246*b1cdbd2cSJim Jagielski catch( const Exception& ) 247*b1cdbd2cSJim Jagielski { 248*b1cdbd2cSJim Jagielski OSL_ENSURE( sal_False, "PropertyHandlerHelper::convertToControlValue: caught an exception while converting via TypeConverter!" ); 249*b1cdbd2cSJim Jagielski } 250*b1cdbd2cSJim Jagielski } 251*b1cdbd2cSJim Jagielski 252*b1cdbd2cSJim Jagielski return aControlValue; 253*b1cdbd2cSJim Jagielski } 254*b1cdbd2cSJim Jagielski 255*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- setContextDocumentModified(const ComponentContext & _rContext)256*b1cdbd2cSJim Jagielski void PropertyHandlerHelper::setContextDocumentModified( const ComponentContext& _rContext ) 257*b1cdbd2cSJim Jagielski { 258*b1cdbd2cSJim Jagielski try 259*b1cdbd2cSJim Jagielski { 260*b1cdbd2cSJim Jagielski Reference< XModifiable > xDocumentModifiable( _rContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY_THROW ); 261*b1cdbd2cSJim Jagielski xDocumentModifiable->setModified( sal_True ); 262*b1cdbd2cSJim Jagielski } 263*b1cdbd2cSJim Jagielski catch( const Exception& ) 264*b1cdbd2cSJim Jagielski { 265*b1cdbd2cSJim Jagielski DBG_UNHANDLED_EXCEPTION(); 266*b1cdbd2cSJim Jagielski } 267*b1cdbd2cSJim Jagielski } 268*b1cdbd2cSJim Jagielski 269*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- getDialogParentWindow(const ComponentContext & _rContext)270*b1cdbd2cSJim Jagielski Window* PropertyHandlerHelper::getDialogParentWindow( const ComponentContext& _rContext ) 271*b1cdbd2cSJim Jagielski { 272*b1cdbd2cSJim Jagielski Window* pInspectorWindow = NULL; 273*b1cdbd2cSJim Jagielski try 274*b1cdbd2cSJim Jagielski { 275*b1cdbd2cSJim Jagielski Reference< XWindow > xInspectorWindow( _rContext.getContextValueByAsciiName( "DialogParentWindow" ), UNO_QUERY_THROW ); 276*b1cdbd2cSJim Jagielski pInspectorWindow = VCLUnoHelper::GetWindow( xInspectorWindow ); 277*b1cdbd2cSJim Jagielski } 278*b1cdbd2cSJim Jagielski catch( const Exception& ) 279*b1cdbd2cSJim Jagielski { 280*b1cdbd2cSJim Jagielski DBG_UNHANDLED_EXCEPTION(); 281*b1cdbd2cSJim Jagielski } 282*b1cdbd2cSJim Jagielski return pInspectorWindow; 283*b1cdbd2cSJim Jagielski } 284*b1cdbd2cSJim Jagielski 285*b1cdbd2cSJim Jagielski //........................................................................ 286*b1cdbd2cSJim Jagielski } // namespace pcr 287*b1cdbd2cSJim Jagielski //........................................................................ 288