in main/vcl/source/window/printdlg.cxx [1179:1760]
void PrintDialog::setupOptionalUI()
{
std::vector< boost::shared_ptr<vcl::RowOrColumn> > aDynamicColumns;
boost::shared_ptr< vcl::RowOrColumn > pCurColumn;
Window* pCurParent = 0, *pDynamicPageParent = 0;
sal_uInt16 nOptPageId = 9, nCurSubGroup = 0;
bool bOnStaticPage = false;
bool bSubgroupOnStaticPage = false;
std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> > aPropertyToDependencyRowMap;
const Sequence< PropertyValue >& rOptions( maPController->getUIOptions() );
for( int i = 0; i < rOptions.getLength(); i++ )
{
Sequence< beans::PropertyValue > aOptProp;
rOptions[i].Value >>= aOptProp;
// extract ui element
bool bEnabled = true;
rtl::OUString aCtrlType;
rtl::OUString aText;
rtl::OUString aPropertyName;
Sequence< rtl::OUString > aChoices;
Sequence< sal_Bool > aChoicesDisabled;
Sequence< rtl::OUString > aHelpTexts;
Sequence< rtl::OUString > aHelpIds;
sal_Int64 nMinValue = 0, nMaxValue = 0;
sal_Int32 nCurHelpText = 0;
rtl::OUString aGroupingHint;
rtl::OUString aDependsOnName;
sal_Int32 nDependsOnValue = 0;
sal_Bool bUseDependencyRow = sal_False;
for( int n = 0; n < aOptProp.getLength(); n++ )
{
const beans::PropertyValue& rEntry( aOptProp[ n ] );
if( rEntry.Name.equalsAscii( "Text" ) )
{
rEntry.Value >>= aText;
}
else if( rEntry.Name.equalsAscii( "ControlType" ) )
{
rEntry.Value >>= aCtrlType;
}
else if( rEntry.Name.equalsAscii( "Choices" ) )
{
rEntry.Value >>= aChoices;
}
else if( rEntry.Name.equalsAscii( "ChoicesDisabled" ) )
{
rEntry.Value >>= aChoicesDisabled;
}
else if( rEntry.Name.equalsAscii( "Property" ) )
{
PropertyValue aVal;
rEntry.Value >>= aVal;
aPropertyName = aVal.Name;
}
else if( rEntry.Name.equalsAscii( "Enabled" ) )
{
sal_Bool bValue = sal_True;
rEntry.Value >>= bValue;
bEnabled = bValue;
}
else if( rEntry.Name.equalsAscii( "GroupingHint" ) )
{
rEntry.Value >>= aGroupingHint;
}
else if( rEntry.Name.equalsAscii( "DependsOnName" ) )
{
rEntry.Value >>= aDependsOnName;
}
else if( rEntry.Name.equalsAscii( "DependsOnEntry" ) )
{
rEntry.Value >>= nDependsOnValue;
}
else if( rEntry.Name.equalsAscii( "AttachToDependency" ) )
{
rEntry.Value >>= bUseDependencyRow;
}
else if( rEntry.Name.equalsAscii( "MinValue" ) )
{
rEntry.Value >>= nMinValue;
}
else if( rEntry.Name.equalsAscii( "MaxValue" ) )
{
rEntry.Value >>= nMaxValue;
}
else if( rEntry.Name.equalsAscii( "HelpText" ) )
{
if( ! (rEntry.Value >>= aHelpTexts) )
{
rtl::OUString aHelpText;
if( (rEntry.Value >>= aHelpText) )
{
aHelpTexts.realloc( 1 );
*aHelpTexts.getArray() = aHelpText;
}
}
}
else if( rEntry.Name.equalsAscii( "HelpId" ) )
{
if( ! (rEntry.Value >>= aHelpIds ) )
{
rtl::OUString aHelpId;
if( (rEntry.Value >>= aHelpId) )
{
aHelpIds.realloc( 1 );
*aHelpIds.getArray() = aHelpId;
}
}
}
else if( rEntry.Name.equalsAscii( "HintNoLayoutPage" ) )
{
sal_Bool bNoLayoutPage = sal_False;
rEntry.Value >>= bNoLayoutPage;
mbShowLayoutPage = ! bNoLayoutPage;
}
}
// bUseDependencyRow should only be true if a dependency exists
bUseDependencyRow = bUseDependencyRow && (aDependsOnName.getLength() != 0);
// is it necessary to switch between static and dynamic pages ?
bool bSwitchPage = false;
if( aGroupingHint.getLength() )
bSwitchPage = true;
else if( aCtrlType.equalsAscii( "Subgroup" ) || (bOnStaticPage && ! bSubgroupOnStaticPage ) )
bSwitchPage = true;
if( bSwitchPage )
{
// restore to dynamic
pCurParent = pDynamicPageParent;
if( ! aDynamicColumns.empty() )
pCurColumn = aDynamicColumns.back();
else
pCurColumn.reset();
bOnStaticPage = false;
bSubgroupOnStaticPage = false;
if( aGroupingHint.equalsAscii( "PrintRange" ) )
{
pCurColumn = maJobPage.mxPrintRange;
pCurParent = &maJobPage; // set job page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.equalsAscii( "OptionsPage" ) )
{
pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maOptionsPage.getLayout());
pCurParent = &maOptionsPage; // set options page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.equalsAscii( "OptionsPageOptGroup" ) )
{
pCurColumn = maOptionsPage.mxOptGroup;
pCurParent = &maOptionsPage; // set options page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.equalsAscii( "LayoutPage" ) )
{
pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maNUpPage.getLayout());
pCurParent = &maNUpPage; // set layout page as current parent
bOnStaticPage = true;
}
else if( aGroupingHint.getLength() )
{
pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maJobPage.getLayout());
pCurParent = &maJobPage; // set job page as current parent
bOnStaticPage = true;
}
}
if( aCtrlType.equalsAscii( "Group" ) ||
( ! pCurParent && ! (bOnStaticPage || aGroupingHint.getLength() ) ) )
{
// add new tab page
TabPage* pNewGroup = new TabPage( &maTabCtrl );
maControls.push_front( pNewGroup );
pDynamicPageParent = pCurParent = pNewGroup;
pNewGroup->SetText( aText );
maTabCtrl.InsertPage( ++nOptPageId, aText );
maTabCtrl.SetTabPage( nOptPageId, pNewGroup );
// set help id
setHelpId( pNewGroup, aHelpIds, 0 );
// set help text
setHelpText( pNewGroup, aHelpTexts, 0 );
// reset subgroup counter
nCurSubGroup = 0;
aDynamicColumns.push_back( boost::dynamic_pointer_cast<vcl::RowOrColumn>(pNewGroup->getLayout()) );
pCurColumn = aDynamicColumns.back();
pCurColumn->setParentWindow( pNewGroup );
bSubgroupOnStaticPage = false;
bOnStaticPage = false;
}
else if( aCtrlType.equalsAscii( "Subgroup" ) && (pCurParent || aGroupingHint.getLength() ) )
{
bSubgroupOnStaticPage = (aGroupingHint.getLength() != 0);
// create group FixedLine
if( ! aGroupingHint.equalsAscii( "PrintRange" ) ||
! pCurColumn->countElements() == 0
)
{
Window* pNewSub = NULL;
if( aGroupingHint.equalsAscii( "PrintRange" ) )
pNewSub = new FixedText( pCurParent, WB_VCENTER );
else
pNewSub = new FixedLine( pCurParent );
maControls.push_front( pNewSub );
pNewSub->SetText( aText );
pNewSub->Show();
// set help id
setHelpId( pNewSub, aHelpIds, 0 );
// set help text
setHelpText( pNewSub, aHelpTexts, 0 );
// add group to current column
pCurColumn->addWindow( pNewSub );
}
// add an indent to the current column
vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), -1 );
pCurColumn->addChild( pIndent );
// and create a column inside the indent
pCurColumn.reset( new vcl::RowOrColumn( pIndent ) );
pIndent->setChild( pCurColumn );
}
// EVIL
else if( aCtrlType.equalsAscii( "Bool" ) &&
aGroupingHint.equalsAscii( "LayoutPage" ) &&
aPropertyName.equalsAscii( "PrintProspect" )
)
{
maNUpPage.maBrochureBtn.SetText( aText );
maNUpPage.maBrochureBtn.Show();
setHelpText( &maNUpPage.maBrochureBtn, aHelpTexts, 0 );
sal_Bool bVal = sal_False;
PropertyValue* pVal = maPController->getValue( aPropertyName );
if( pVal )
pVal->Value >>= bVal;
maNUpPage.maBrochureBtn.Check( bVal );
maNUpPage.maBrochureBtn.Enable( maPController->isUIOptionEnabled( aPropertyName ) && pVal != NULL );
maNUpPage.maBrochureBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
maPropertyToWindowMap[ aPropertyName ].push_back( &maNUpPage.maBrochureBtn );
maControlToPropertyMap[&maNUpPage.maBrochureBtn] = aPropertyName;
aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, maNUpPage.mxBrochureDep ) );
}
else
{
boost::shared_ptr<vcl::RowOrColumn> pSaveCurColumn( pCurColumn );
if( bUseDependencyRow )
{
// find the correct dependency row (if any)
std::pair< std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator,
std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator > aDepRange;
aDepRange = aPropertyToDependencyRowMap.equal_range( aDependsOnName );
if( aDepRange.first != aDepRange.second )
{
while( nDependsOnValue && aDepRange.first != aDepRange.second )
{
nDependsOnValue--;
++aDepRange.first;
}
if( aDepRange.first != aPropertyToDependencyRowMap.end() )
{
pCurColumn = aDepRange.first->second;
maReverseDependencySet.insert( aPropertyName );
}
}
}
if( aCtrlType.equalsAscii( "Bool" ) && pCurParent )
{
// add a check box
CheckBox* pNewBox = new CheckBox( pCurParent );
maControls.push_front( pNewBox );
pNewBox->SetText( aText );
pNewBox->Show();
sal_Bool bVal = sal_False;
PropertyValue* pVal = maPController->getValue( aPropertyName );
if( pVal )
pVal->Value >>= bVal;
pNewBox->Check( bVal );
pNewBox->SetToggleHdl( LINK( this, PrintDialog, UIOption_CheckHdl ) );
maPropertyToWindowMap[ aPropertyName ].push_back( pNewBox );
maControlToPropertyMap[pNewBox] = aPropertyName;
// set help id
setHelpId( pNewBox, aHelpIds, 0 );
// set help text
setHelpText( pNewBox, aHelpTexts, 0 );
boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pCurColumn.get(), false ) );
pCurColumn->addChild( pDependencyRow );
aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
// add checkbox to current column
pDependencyRow->addWindow( pNewBox );
}
else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent )
{
boost::shared_ptr<vcl::RowOrColumn> pRadioColumn( pCurColumn );
if( aText.getLength() )
{
// add a FixedText:
FixedText* pHeading = new FixedText( pCurParent );
maControls.push_front( pHeading );
pHeading->SetText( aText );
pHeading->Show();
// set help id
setHelpId( pHeading, aHelpIds, nCurHelpText );
// set help text
setHelpText( pHeading, aHelpTexts, nCurHelpText );
nCurHelpText++;
// add fixed text to current column
pCurColumn->addWindow( pHeading );
// add an indent to the current column
vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), 15 );
pCurColumn->addChild( pIndent );
// and create a column inside the indent
pRadioColumn.reset( new vcl::RowOrColumn( pIndent ) );
pIndent->setChild( pRadioColumn );
}
// iterate options
sal_Int32 nSelectVal = 0;
PropertyValue* pVal = maPController->getValue( aPropertyName );
if( pVal && pVal->Value.hasValue() )
pVal->Value >>= nSelectVal;
for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
{
boost::shared_ptr<vcl::LabeledElement> pLabel( new vcl::LabeledElement( pRadioColumn.get(), 1 ) );
pRadioColumn->addChild( pLabel );
boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pLabel.get(), false ) );
pLabel->setElement( pDependencyRow );
aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
RadioButton* pBtn = new RadioButton( pCurParent, m == 0 ? WB_GROUP : 0 );
maControls.push_front( pBtn );
pBtn->SetText( aChoices[m] );
pBtn->Check( m == nSelectVal );
pBtn->SetToggleHdl( LINK( this, PrintDialog, UIOption_RadioHdl ) );
if( aChoicesDisabled.getLength() > m && aChoicesDisabled[m] == sal_True )
pBtn->Enable( sal_False );
pBtn->Show();
maPropertyToWindowMap[ aPropertyName ].push_back( pBtn );
maControlToPropertyMap[pBtn] = aPropertyName;
maControlToNumValMap[pBtn] = m;
// set help id
setHelpId( pBtn, aHelpIds, nCurHelpText );
// set help text
setHelpText( pBtn, aHelpTexts, nCurHelpText );
nCurHelpText++;
// add the radio button to the column
pLabel->setLabel( pBtn );
}
}
else if( ( aCtrlType.equalsAscii( "List" ) ||
aCtrlType.equalsAscii( "Range" ) ||
aCtrlType.equalsAscii( "Edit" )
) && pCurParent )
{
// create a row in the current column
boost::shared_ptr<vcl::RowOrColumn> pFieldColumn( new vcl::RowOrColumn( pCurColumn.get(), false ) );
pCurColumn->addChild( pFieldColumn );
aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pFieldColumn ) );
vcl::LabeledElement* pLabel = NULL;
if( aText.getLength() )
{
// add a FixedText:
FixedText* pHeading = new FixedText( pCurParent, WB_VCENTER );
maControls.push_front( pHeading );
pHeading->SetText( aText );
pHeading->Show();
// add to row
pLabel = new vcl::LabeledElement( pFieldColumn.get(), 2 );
pFieldColumn->addChild( pLabel );
pLabel->setLabel( pHeading );
}
if( aCtrlType.equalsAscii( "List" ) )
{
ListBox* pList = new ListBox( pCurParent, WB_DROPDOWN | WB_BORDER );
maControls.push_front( pList );
// iterate options
for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
{
pList->InsertEntry( aChoices[m] );
}
sal_Int32 nSelectVal = 0;
PropertyValue* pVal = maPController->getValue( aPropertyName );
if( pVal && pVal->Value.hasValue() )
pVal->Value >>= nSelectVal;
pList->SelectEntryPos( static_cast<sal_uInt16>(nSelectVal) );
pList->SetSelectHdl( LINK( this, PrintDialog, UIOption_SelectHdl ) );
pList->SetDropDownLineCount( static_cast<sal_uInt16>(aChoices.getLength()) );
pList->Show();
// set help id
setHelpId( pList, aHelpIds, 0 );
// set help text
setHelpText( pList, aHelpTexts, 0 );
maPropertyToWindowMap[ aPropertyName ].push_back( pList );
maControlToPropertyMap[pList] = aPropertyName;
// finish the pair
if( pLabel )
pLabel->setElement( pList );
else
pFieldColumn->addWindow( pList );
}
else if( aCtrlType.equalsAscii( "Range" ) )
{
NumericField* pField = new NumericField( pCurParent, WB_BORDER | WB_SPIN );
maControls.push_front( pField );
// set min/max and current value
if( nMinValue != nMaxValue )
{
pField->SetMin( nMinValue );
pField->SetMax( nMaxValue );
}
sal_Int64 nCurVal = 0;
PropertyValue* pVal = maPController->getValue( aPropertyName );
if( pVal && pVal->Value.hasValue() )
pVal->Value >>= nCurVal;
pField->SetValue( nCurVal );
pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
pField->Show();
// set help id
setHelpId( pField, aHelpIds, 0 );
// set help text
setHelpText( pField, aHelpTexts, 0 );
maPropertyToWindowMap[ aPropertyName ].push_back( pField );
maControlToPropertyMap[pField] = aPropertyName;
// add to row
if( pLabel )
pLabel->setElement( pField );
else
pFieldColumn->addWindow( pField );
}
else if( aCtrlType.equalsAscii( "Edit" ) )
{
Edit* pField = new Edit( pCurParent, WB_BORDER );
maControls.push_front( pField );
rtl::OUString aCurVal;
PropertyValue* pVal = maPController->getValue( aPropertyName );
if( pVal && pVal->Value.hasValue() )
pVal->Value >>= aCurVal;
pField->SetText( aCurVal );
pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
pField->Show();
// set help id
setHelpId( pField, aHelpIds, 0 );
// set help text
setHelpText( pField, aHelpTexts, 0 );
maPropertyToWindowMap[ aPropertyName ].push_back( pField );
maControlToPropertyMap[pField] = aPropertyName;
// add to row
if( pLabel )
pLabel->setElement( pField );
else
pFieldColumn->addWindow( pField, 2 );
}
}
else
{
DBG_ERROR( "Unsupported UI option" );
}
pCurColumn = pSaveCurColumn;
}
}
// #i106506# if no brochure button, then the singular Pages radio button
// makes no sense, so replace it by a FixedText label
if( ! maNUpPage.maBrochureBtn.IsVisible() )
{
if( maNUpPage.mxPagesBtnLabel.get() )
{
maNUpPage.maPagesBoxTitleTxt.SetText( maNUpPage.maPagesBtn.GetText() );
maNUpPage.maPagesBoxTitleTxt.Show( sal_True );
maNUpPage.mxPagesBtnLabel->setLabel( &maNUpPage.maPagesBoxTitleTxt );
maNUpPage.maPagesBtn.Show( sal_False );
}
}
// update enable states
checkOptionalControlDependencies();
// print range empty (currently math only) -> hide print range and spacer line
if( maJobPage.mxPrintRange->countElements() == 0 )
{
maJobPage.mxPrintRange->show( false, false );
maJobPage.maCopySpacer.Show( sal_False );
maJobPage.maReverseOrderBox.Show( sal_False );
}
else
{
// add an indent to the current column
vcl::Indenter* pIndent = new vcl::Indenter( maJobPage.mxPrintRange.get(), -1 );
maJobPage.mxPrintRange->addChild( pIndent );
// and create a column inside the indent
pIndent->setWindow( &maJobPage.maReverseOrderBox );
maJobPage.maReverseOrderBox.Show( sal_True );
}
#ifdef WNT
// FIXME: the GetNativeControlRegion call on Windows has some issues
// (which skew the results of GetOptimalSize())
// however fixing this thoroughly needs to take interaction with paint into
// account, making the right fix less simple. Fix this the right way
// at some point. For now simply add some space at the lowest element
size_t nIndex = maJobPage.getLayout()->countElements();
if( nIndex > 0 ) // sanity check
maJobPage.getLayout()->setBorders( nIndex-1, 0, 0, 0, -1 );
#endif
// create auto mnemomnics now so they can be calculated in layout
ImplWindowAutoMnemonic( &maJobPage );
ImplWindowAutoMnemonic( &maNUpPage );
ImplWindowAutoMnemonic( &maOptionsPage );
ImplWindowAutoMnemonic( this );
// calculate job page
Size aMaxSize = maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
// and layout page
updateMaxSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
// and options page
updateMaxSize( maOptionsPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
for( std::vector< boost::shared_ptr<vcl::RowOrColumn> >::iterator it = aDynamicColumns.begin();
it != aDynamicColumns.end(); ++it )
{
Size aPageSize( (*it)->getOptimalSize( WINDOWSIZE_PREFERRED ) );
updateMaxSize( aPageSize, aMaxSize );
}
// resize dialog if necessary
Size aTabSize = maTabCtrl.GetTabPageSizePixel();
maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
if( aMaxSize.Height() > aTabSize.Height() || aMaxSize.Width() > aTabSize.Width() )
{
Size aCurSize( GetOutputSizePixel() );
if( aMaxSize.Height() > aTabSize.Height() )
{
aCurSize.Height() += aMaxSize.Height() - aTabSize.Height();
aTabSize.Height() = aMaxSize.Height();
}
if( aMaxSize.Width() > aTabSize.Width() )
{
aCurSize.Width() += aMaxSize.Width() - aTabSize.Width();
// and the tab ctrl needs more space, too
aTabSize.Width() = aMaxSize.Width();
}
maTabCtrl.SetTabPageSizePixel( aTabSize );
maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
}
Size aSz = getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
SetOutputSizePixel( aSz );
}