1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "Condition.hxx"
21 #include <UITools.hxx>
22 #include <CondFormat.hxx>
23 #include <core_resource.hxx>
24 #include <strings.hrc>
25 #include <ReportController.hxx>
26 #include <ColorChanger.hxx>
27 #include <reportformula.hxx>
28 #include <com/sun/star/util/URL.hpp>
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
31 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
32 #include <com/sun/star/ui/XImageManager.hpp>
33 #include <com/sun/star/awt/FontDescriptor.hpp>
34 #include <com/sun/star/ui/ImageType.hpp>
36 #include <svx/PaletteManager.hxx>
37 #include <svx/tbcontrl.hxx>
38 #include <svx/svxids.hrc>
39 #include <svx/xtable.hxx>
40 #include <svx/tbxcolorupdate.hxx>
41 #include <toolkit/helper/vclunohelper.hxx>
42 #include <svtools/imgdef.hxx>
43 #include <unotools/pathoptions.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/bitmapaccess.hxx>
46 #include <vcl/settings.hxx>
48 #include <tools/diagnose_ex.h>
49 #include <rtl/ustrbuf.hxx>
50 #include <svtools/valueset.hxx>
54 using namespace ::com::sun::star
;
55 using namespace ::com::sun::star::uno
;
56 using namespace ::com::sun::star::beans
;
58 ConditionField::ConditionField(Condition
* pParent
, Edit
* pSubEdit
, PushButton
*pFormula
)
60 , m_pSubEdit(pSubEdit
)
61 , m_pFormula(pFormula
)
63 m_pSubEdit
->EnableRTL( false );
65 m_pFormula
->SetText("...");
66 m_pFormula
->SetClickHdl( LINK( this, ConditionField
, OnFormula
) );
69 IMPL_LINK( ConditionField
, OnFormula
, Button
*, _pClickedButton
, void )
71 OUString
sFormula(m_pSubEdit
->GetText());
72 const sal_Int32 nLen
= sFormula
.getLength();
75 ReportFormula
aFormula( sFormula
);
76 sFormula
= aFormula
.getCompleteFormula();
78 uno::Reference
< awt::XWindow
> xInspectorWindow
= VCLUnoHelper::GetInterface(_pClickedButton
);
79 uno::Reference
< beans::XPropertySet
> xProp(m_pParent
->getController().getRowSet(),uno::UNO_QUERY
);
80 if ( rptui::openDialogFormula_nothrow( sFormula
, m_pParent
->getController().getContext(),xInspectorWindow
,xProp
) )
82 ReportFormula
aFormula( sFormula
);
83 m_pSubEdit
->SetText(aFormula
.getUndecoratedContent());
87 ConditionColorWrapper::ConditionColorWrapper(Condition
* pControl
)
93 void ConditionColorWrapper::dispose()
98 void ConditionColorWrapper::operator()(const OUString
& /*rCommand*/, const NamedColor
& rNamedColor
)
100 mxControl
->ApplyCommand(mnSlotId
, rNamedColor
);
106 Condition::Condition( vcl::Window
* _pParent
, IConditionalFormatAction
& _rAction
, ::rptui::OReportController
& _rController
)
108 , m_xPaletteManager(new PaletteManager
)
109 , m_aColorWrapper(this)
110 , m_rController(_rController
)
111 , m_rAction(_rAction
)
113 , m_bInDestruction(false)
115 m_pUIBuilder
.reset(new VclBuilder(this, getUIRootDir(), "modules/dbreport/ui/conditionwin.ui"));
117 get(m_pHeader
, "headerLabel");
118 get(m_pConditionType
, "typeCombobox");
119 get(m_pOperationList
, "opCombobox");
120 m_pCondLHS
.reset( new ConditionField(this, get
<Edit
>("lhsEntry"), get
<PushButton
>("lhsButton")) );
121 get(m_pOperandGlue
, "andLabel");
122 m_pCondRHS
.reset( new ConditionField(this, get
<Edit
>("rhsEntry"), get
<PushButton
>("rhsButton")) );
123 get(m_pActions
, "formatToolbox");
124 get(m_pPreview
, "previewDrawingarea");
125 get(m_pMoveUp
, "upButton");
126 get(m_pMoveDown
, "downButton");
127 get(m_pAddCondition
, "addButton");
128 get(m_pRemoveCondition
, "removeButton");
130 m_pActions
->SetLineSpacing(true);
131 m_pCondLHS
->GrabFocus();
133 m_pConditionType
->SetSelectHdl( LINK( this, Condition
, OnTypeSelected
) );
135 m_pOperationList
->SetDropDownLineCount( 10 );
136 m_pOperationList
->SetSelectHdl( LINK( this, Condition
, OnOperationSelected
) );
138 m_pActions
->SetSelectHdl(LINK(this, Condition
, OnFormatAction
));
139 m_pActions
->SetDropdownClickHdl( LINK( this, Condition
, DropdownClick
) );
140 setToolBox(m_pActions
);
142 m_pMoveUp
->SetClickHdl( LINK( this, Condition
, OnConditionAction
) );
143 m_pMoveDown
->SetClickHdl( LINK( this, Condition
, OnConditionAction
) );
144 m_pAddCondition
->SetClickHdl( LINK( this, Condition
, OnConditionAction
) );
145 m_pRemoveCondition
->SetClickHdl( LINK( this, Condition
, OnConditionAction
) );
147 vcl::Font
aFont( m_pAddCondition
->GetFont() );
148 aFont
.SetWeight( WEIGHT_BOLD
);
149 m_pAddCondition
->SetFont( aFont
);
150 m_pRemoveCondition
->SetFont( aFont
);
152 m_pOperandGlue
->SetStyle( m_pOperandGlue
->GetStyle() | WB_VCENTER
);
154 m_pConditionType
->SelectEntryPos( 0 );
155 m_pOperationList
->SelectEntryPos( 0 );
157 m_nBoldId
= m_pActions
->GetItemId(".uno:Bold");
158 m_nItalicId
= m_pActions
->GetItemId(".uno:Italic");
159 m_nUnderLineId
= m_pActions
->GetItemId(".uno:Underline");
160 m_nBackgroundColorId
= m_pActions
->GetItemId(".uno:BackgroundColor");
161 m_nFontColorId
= m_pActions
->GetItemId(".uno:FontColor");
162 m_nFontDialogId
= m_pActions
->GetItemId(".uno:FontDialog");
164 m_pBtnUpdaterBackgroundColor
.reset( new svx::ToolboxButtonColorUpdater(
165 SID_BACKGROUND_COLOR
, m_nBackgroundColorId
, m_pActions
, false,
166 m_pActions
->GetItemText( m_nBackgroundColorId
) ) );
167 m_pBtnUpdaterFontColor
.reset( new svx::ToolboxButtonColorUpdater(
168 SID_ATTR_CHAR_COLOR2
, m_nFontColorId
, m_pActions
, false,
169 m_pActions
->GetItemText( m_nFontColorId
) ) );
173 ConditionalExpressionFactory::getKnownConditionalExpressions( m_aConditionalExpressions
);
176 sal_uInt16
Condition::mapToolbarItemToSlotId(sal_uInt16 nItemId
) const
178 if (nItemId
== m_nBoldId
)
179 return SID_ATTR_CHAR_WEIGHT
;
180 if (nItemId
== m_nItalicId
)
181 return SID_ATTR_CHAR_POSTURE
;
182 if (nItemId
== m_nUnderLineId
)
183 return SID_ATTR_CHAR_UNDERLINE
;
184 if (nItemId
== m_nBackgroundColorId
)
185 return SID_BACKGROUND_COLOR
;
186 if (nItemId
== m_nFontColorId
)
187 return SID_ATTR_CHAR_COLOR2
;
188 if (nItemId
== m_nFontDialogId
)
193 Condition::~Condition()
198 void Condition::dispose()
200 m_bInDestruction
= true;
202 m_pBtnUpdaterFontColor
.reset();
205 m_pBtnUpdaterBackgroundColor
.reset();
207 m_pConditionType
.clear();
208 m_pOperationList
.clear();
209 m_pOperandGlue
.clear();
214 m_pAddCondition
.clear();
215 m_pRemoveCondition
.clear();
216 m_pColorFloat
.disposeAndClear();
217 m_aColorWrapper
.dispose();
222 IMPL_LINK(Condition
, DropdownClick
, ToolBox
*, pToolBox
, void)
224 sal_uInt16
nId( m_pActions
->GetCurItemId() );
225 m_pColorFloat
.disposeAndClear();
226 sal_uInt16
nSlotId(mapToolbarItemToSlotId(nId
));
227 m_aColorWrapper
.SetSlotId(nSlotId
);
228 m_pColorFloat
= VclPtr
<SvxColorWindow
>::Create(
229 OUString() /*m_aCommandURL*/,
238 m_pColorFloat
->EnableDocking();
239 vcl::Window::GetDockingManager()->StartPopupMode(pToolBox
, m_pColorFloat
, FloatWinPopupFlags::GrabFocus
);
242 IMPL_LINK_NOARG( Condition
, OnFormatAction
, ToolBox
*, void )
244 ApplyCommand(mapToolbarItemToSlotId(m_pActions
->GetCurItemId()),
245 NamedColor(COL_AUTO
, "#" + COL_AUTO
.AsRGBHexString()));
248 IMPL_LINK( Condition
, OnConditionAction
, Button
*, _pClickedButton
, void )
250 if ( _pClickedButton
== m_pMoveUp
)
251 m_rAction
.moveConditionUp( getConditionIndex() );
252 else if ( _pClickedButton
== m_pMoveDown
)
253 m_rAction
.moveConditionDown( getConditionIndex() );
254 else if ( _pClickedButton
== m_pAddCondition
)
255 m_rAction
.addCondition( getConditionIndex() );
256 else if ( _pClickedButton
== m_pRemoveCondition
)
257 m_rAction
.deleteCondition( getConditionIndex() );
260 void Condition::ApplyCommand( sal_uInt16 _nCommandId
, const NamedColor
& rNamedColor
)
262 if ( _nCommandId
== SID_ATTR_CHAR_COLOR2
)
263 m_pBtnUpdaterFontColor
->Update( rNamedColor
);
264 else if ( _nCommandId
== SID_BACKGROUND_COLOR
)
265 m_pBtnUpdaterBackgroundColor
->Update( rNamedColor
);
267 m_rAction
.applyCommand( m_nCondIndex
, _nCommandId
, rNamedColor
.first
);
270 void Condition::setImageList(sal_Int16
/*_eBitmapSet*/)
274 void Condition::resizeControls(const Size
& /*_rDiff*/)
278 void Condition::GetFocus()
281 if ( !m_bInDestruction
)
282 m_pCondLHS
->GrabFocus();
285 IMPL_LINK_NOARG( Condition
, OnTypeSelected
, ListBox
&, void )
287 impl_layoutOperands();
291 IMPL_LINK_NOARG( Condition
, OnOperationSelected
, ListBox
&, void )
293 impl_layoutOperands();
296 void Condition::impl_layoutOperands()
298 const ConditionType
eType( impl_getCurrentConditionType() );
299 const ComparisonOperation
eOperation( impl_getCurrentComparisonOperation() );
301 const bool bIsExpression
= ( eType
== eExpression
);
302 const bool bHaveRHS
=
303 ( ( eType
== eFieldValueComparison
)
304 && ( ( eOperation
== eBetween
)
305 || ( eOperation
== eNotBetween
)
309 // the "condition type" list box
310 m_pOperationList
->Show( !bIsExpression
);
311 m_pOperandGlue
->Show( bHaveRHS
);
312 m_pCondRHS
->Show( bHaveRHS
);
315 void Condition::impl_setCondition( const OUString
& _rConditionFormula
)
317 // determine the condition's type and comparison operation
318 ConditionType
eType( eFieldValueComparison
);
319 ComparisonOperation
eOperation( eBetween
);
321 // LHS and RHS, matched below
324 if ( !_rConditionFormula
.isEmpty() )
326 // the unprefixed expression which forms the condition
327 ReportFormula
aFormula( _rConditionFormula
);
328 OSL_ENSURE( aFormula
.getType() == ReportFormula::Expression
, "Condition::setCondition: illegal formula!" );
329 OUString sExpression
;
330 if ( aFormula
.getType() == ReportFormula::Expression
)
331 sExpression
= aFormula
.getExpression();
332 // as fallback, if the below matching does not succeed, assume
333 // the whole expression is the LHS
337 // the data field (or expression) to which our control is bound
338 const ReportFormula
aFieldContentFormula( m_rAction
.getDataField() );
339 const OUString
sUnprefixedFieldContent( aFieldContentFormula
.getBracketedFieldOrExpression() );
341 // check whether one of the Field Value Expression Factories recognizes the expression
342 for (const auto& [rOperation
, rxConditionalExpression
] : m_aConditionalExpressions
)
344 if ( rxConditionalExpression
->matchExpression( sExpression
, sUnprefixedFieldContent
, sLHS
, sRHS
) )
346 eType
= eFieldValueComparison
;
347 eOperation
= rOperation
;
354 m_pConditionType
->SelectEntryPos( static_cast<sal_uInt16
>(eType
) );
355 m_pOperationList
->SelectEntryPos( static_cast<sal_uInt16
>(eOperation
) );
356 m_pCondLHS
->SetText( sLHS
);
357 m_pCondRHS
->SetText( sRHS
);
360 impl_layoutOperands();
364 void Condition::setCondition( const uno::Reference
< report::XFormatCondition
>& _rxCondition
)
366 OSL_PRECOND( _rxCondition
.is(), "Condition::setCondition: empty condition object!" );
367 if ( !_rxCondition
.is() )
370 OUString sConditionFormula
;
373 if ( _rxCondition
.is() )
374 sConditionFormula
= _rxCondition
->getFormula();
376 catch( const Exception
& )
378 DBG_UNHANDLED_EXCEPTION("reportdesign");
380 impl_setCondition( sConditionFormula
);
381 updateToolbar( _rxCondition
.get() );
385 void Condition::updateToolbar(const uno::Reference
< report::XReportControlFormat
>& _xReportControlFormat
)
387 OSL_ENSURE(_xReportControlFormat
.is(),"XReportControlFormat is NULL!");
388 if ( _xReportControlFormat
.is() )
390 ToolBox::ImplToolItems::size_type nItemCount
= m_pActions
->GetItemCount();
391 for (ToolBox::ImplToolItems::size_type j
= 0; j
< nItemCount
; ++j
)
393 sal_uInt16 nItemId
= m_pActions
->GetItemId(j
);
394 m_pActions
->CheckItem( nItemId
, OReportController::isFormatCommandEnabled(mapToolbarItemToSlotId(nItemId
),
395 _xReportControlFormat
) );
400 vcl::Font
aBaseFont( Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetAppFont() );
401 SvxFont
aFont( VCLUnoHelper::CreateFont( _xReportControlFormat
->getFontDescriptor(), aBaseFont
) );
402 aFont
.SetFontHeight(OutputDevice::LogicToLogic(Size(0, aFont
.GetFontHeight()), MapMode(MapUnit::MapPoint
), MapMode(MapUnit::MapTwip
)).Height());
403 aFont
.SetEmphasisMark( static_cast< FontEmphasisMark
>( _xReportControlFormat
->getControlTextEmphasis() ) );
404 aFont
.SetRelief( static_cast< FontRelief
>( _xReportControlFormat
->getCharRelief() ) );
405 aFont
.SetColor( Color(_xReportControlFormat
->getCharColor()) );
406 m_pPreview
->SetFont( aFont
, aFont
, aFont
);
407 m_pPreview
->SetBackColor( Color(_xReportControlFormat
->getControlBackground()) );
408 m_pPreview
->SetTextLineColor( Color( _xReportControlFormat
->getCharUnderlineColor() ) );
410 catch( const Exception
& )
412 DBG_UNHANDLED_EXCEPTION("reportdesign");
417 void Condition::fillFormatCondition(const uno::Reference
< report::XFormatCondition
>& _xCondition
)
419 const ConditionType
eType( impl_getCurrentConditionType() );
420 const ComparisonOperation
eOperation( impl_getCurrentComparisonOperation() );
422 const OUString
sLHS( m_pCondLHS
->GetText() );
423 const OUString
sRHS( m_pCondRHS
->GetText() );
425 OUString
sUndecoratedFormula( sLHS
);
427 if ( eType
== eFieldValueComparison
)
429 ReportFormula
aFieldContentFormula( m_rAction
.getDataField() );
430 OUString
sUnprefixedFieldContent( aFieldContentFormula
.getBracketedFieldOrExpression() );
432 PConditionalExpression
pFactory( m_aConditionalExpressions
[ eOperation
] );
433 sUndecoratedFormula
= pFactory
->assembleExpression( sUnprefixedFieldContent
, sLHS
, sRHS
);
436 ReportFormula
aFormula( ReportFormula::Expression
, sUndecoratedFormula
);
437 _xCondition
->setFormula( aFormula
.getCompleteFormula() );
440 void Condition::setConditionIndex( size_t _nCondIndex
, size_t _nCondCount
)
442 m_nCondIndex
= _nCondIndex
;
443 OUString
sHeader( RptResId( STR_NUMBERED_CONDITION
) );
444 sHeader
= sHeader
.replaceFirst( "$number$", OUString::number( _nCondIndex
+ 1) );
445 m_pHeader
->SetText( sHeader
);
447 m_pMoveUp
->Enable( _nCondIndex
> 0 );
448 OSL_PRECOND( _nCondCount
> 0, "Condition::setConditionIndex: having no conditions at all is nonsense!" );
449 m_pMoveDown
->Enable( _nCondIndex
< _nCondCount
- 1 );
453 bool Condition::isEmpty() const
455 return m_pCondLHS
->GetText().isEmpty();
462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */