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
, std::unique_ptr
<weld::Entry
> xSubEdit
,
59 std::unique_ptr
<weld::Button
> xFormula
)
61 , m_xSubEdit(std::move(xSubEdit
))
62 , m_xFormula(std::move(xFormula
))
64 m_xFormula
->set_label("...");
65 m_xFormula
->connect_clicked( LINK( this, ConditionField
, OnFormula
) );
68 IMPL_LINK_NOARG(ConditionField
, OnFormula
, weld::Button
&, void)
70 OUString
sFormula(m_xSubEdit
->get_text());
71 const sal_Int32 nLen
= sFormula
.getLength();
74 ReportFormula
aFormula( sFormula
);
75 sFormula
= aFormula
.getCompleteFormula();
77 uno::Reference
< awt::XWindow
> xInspectorWindow
= m_pParent
->GetXWindow();
78 uno::Reference
< beans::XPropertySet
> xProp(m_pParent
->getController().getRowSet(),uno::UNO_QUERY
);
79 if ( rptui::openDialogFormula_nothrow( sFormula
, m_pParent
->getController().getContext(),xInspectorWindow
,xProp
) )
81 ReportFormula
aFormula( sFormula
);
82 m_xSubEdit
->set_text(aFormula
.getUndecoratedContent());
86 ConditionColorWrapper::ConditionColorWrapper(Condition
* pControl
, sal_uInt16 nSlotId
)
92 void ConditionColorWrapper::operator()(const OUString
& /*rCommand*/, const NamedColor
& rNamedColor
)
94 mpControl
->ApplyCommand(mnSlotId
, rNamedColor
);
98 Condition::Condition(weld::Container
* pParent
, weld::Window
* pDialog
, IConditionalFormatAction
& _rAction
, ::rptui::OReportController
& _rController
)
99 : m_xPaletteManager(new PaletteManager
)
100 , m_aBackColorWrapper(this, SID_BACKGROUND_COLOR
)
101 , m_aForeColorWrapper(this, SID_ATTR_CHAR_COLOR2
)
102 , m_rController(_rController
)
103 , m_rAction(_rAction
)
106 , m_xBuilder(Application::CreateBuilder(pParent
, "modules/dbreport/ui/conditionwin.ui"))
107 , m_xContainer(m_xBuilder
->weld_container("ConditionWin"))
108 , m_xHeader(m_xBuilder
->weld_label("headerLabel"))
109 , m_xConditionType(m_xBuilder
->weld_combo_box("typeCombobox"))
110 , m_xOperationList(m_xBuilder
->weld_combo_box("opCombobox"))
111 , m_xOperandGlue(m_xBuilder
->weld_label("andLabel"))
112 , m_xActions(m_xBuilder
->weld_toolbar("formatToolbox"))
113 , m_xPreview(new weld::CustomWeld(*m_xBuilder
, "previewDrawingarea", m_aPreview
))
114 , m_xMoveUp(m_xBuilder
->weld_button("upButton"))
115 , m_xMoveDown(m_xBuilder
->weld_button("downButton"))
116 , m_xAddCondition(m_xBuilder
->weld_button("addButton"))
117 , m_xRemoveCondition(m_xBuilder
->weld_button("removeButton"))
119 m_xCondLHS
.reset(new ConditionField(this, m_xBuilder
->weld_entry("lhsEntry"), m_xBuilder
->weld_button("lhsButton")));
120 m_xCondRHS
.reset(new ConditionField(this, m_xBuilder
->weld_entry("rhsEntry"), m_xBuilder
->weld_button("rhsButton")));
122 m_xCondLHS
->grab_focus();
124 m_xConditionType
->connect_changed( LINK( this, Condition
, OnTypeSelected
) );
126 m_xOperationList
->connect_changed( LINK( this, Condition
, OnOperationSelected
) );
128 m_xActions
->connect_clicked(LINK(this, Condition
, OnFormatAction
));
130 m_xMoveUp
->connect_clicked( LINK( this, Condition
, OnConditionAction
) );
131 m_xMoveDown
->connect_clicked( LINK( this, Condition
, OnConditionAction
) );
132 m_xAddCondition
->connect_clicked( LINK( this, Condition
, OnConditionAction
) );
133 m_xRemoveCondition
->connect_clicked( LINK( this, Condition
, OnConditionAction
) );
135 m_xConditionType
->set_active(0);
136 m_xOperationList
->set_active(0);
138 SetBackgroundDropdownClick();
139 SetForegroundDropdownClick();
141 m_xContainer
->show();
143 ConditionalExpressionFactory::getKnownConditionalExpressions( m_aConditionalExpressions
);
146 sal_uInt16
Condition::mapToolbarItemToSlotId(const OString
& rItemId
)
148 if (rItemId
== "bold")
149 return SID_ATTR_CHAR_WEIGHT
;
150 if (rItemId
== "italic")
151 return SID_ATTR_CHAR_POSTURE
;
152 if (rItemId
== "underline")
153 return SID_ATTR_CHAR_UNDERLINE
;
154 if (rItemId
== "background")
155 return SID_BACKGROUND_COLOR
;
156 if (rItemId
== "foreground")
157 return SID_ATTR_CHAR_COLOR2
;
158 if (rItemId
== "fontdialog")
163 Condition::~Condition()
167 void Condition::SetBackgroundDropdownClick()
169 m_xBackColorFloat
.reset(new ColorWindow(
172 SID_BACKGROUND_COLOR
,
175 MenuOrToolMenuButton(m_xActions
.get(), "background"),
176 m_aBackColorWrapper
));
178 m_xActions
->set_item_popover("background", m_xBackColorFloat
->GetWidget());
181 void Condition::SetForegroundDropdownClick()
183 m_xForeColorFloat
.reset(new ColorWindow(
186 SID_ATTR_CHAR_COLOR2
,
189 MenuOrToolMenuButton(m_xActions
.get(), "foreground"),
190 m_aForeColorWrapper
));
192 m_xActions
->set_item_popover("foreground", m_xForeColorFloat
->GetWidget());
196 IMPL_LINK(Condition
, OnFormatAction
, const OString
&, rIdent
, void)
198 ApplyCommand(mapToolbarItemToSlotId(rIdent
),
199 NamedColor(COL_AUTO
, "#" + COL_AUTO
.AsRGBHexString()));
202 IMPL_LINK(Condition
, OnConditionAction
, weld::Button
&, rClickedButton
, void)
204 if ( &rClickedButton
== m_xMoveUp
.get() )
205 m_rAction
.moveConditionUp( getConditionIndex() );
206 else if ( &rClickedButton
== m_xMoveDown
.get() )
207 m_rAction
.moveConditionDown( getConditionIndex() );
208 else if ( &rClickedButton
== m_xAddCondition
.get() )
209 m_rAction
.addCondition( getConditionIndex() );
210 else if ( &rClickedButton
== m_xRemoveCondition
.get() )
211 m_rAction
.deleteCondition( getConditionIndex() );
214 void Condition::ApplyCommand( sal_uInt16 _nCommandId
, const NamedColor
& rNamedColor
)
216 m_rAction
.applyCommand( m_nCondIndex
, _nCommandId
, rNamedColor
.first
);
219 IMPL_LINK_NOARG( Condition
, OnTypeSelected
, weld::ComboBox
&, void )
221 impl_layoutOperands();
224 IMPL_LINK_NOARG( Condition
, OnOperationSelected
, weld::ComboBox
&, void )
226 impl_layoutOperands();
229 void Condition::impl_layoutOperands()
231 const ConditionType
eType( impl_getCurrentConditionType() );
232 const ComparisonOperation
eOperation( impl_getCurrentComparisonOperation() );
234 const bool bIsExpression
= ( eType
== eExpression
);
235 const bool bHaveRHS
=
236 ( ( eType
== eFieldValueComparison
)
237 && ( ( eOperation
== eBetween
)
238 || ( eOperation
== eNotBetween
)
242 // the "condition type" list box
243 m_xOperationList
->set_visible( !bIsExpression
);
244 m_xOperandGlue
->set_visible( bHaveRHS
);
245 m_xCondRHS
->set_visible( bHaveRHS
);
248 void Condition::impl_setCondition( const OUString
& _rConditionFormula
)
250 // determine the condition's type and comparison operation
251 ConditionType
eType( eFieldValueComparison
);
252 ComparisonOperation
eOperation( eBetween
);
254 // LHS and RHS, matched below
257 if ( !_rConditionFormula
.isEmpty() )
259 // the unprefixed expression which forms the condition
260 ReportFormula
aFormula( _rConditionFormula
);
261 OSL_ENSURE( aFormula
.getType() == ReportFormula::Expression
, "Condition::setCondition: illegal formula!" );
262 OUString sExpression
;
263 if ( aFormula
.getType() == ReportFormula::Expression
)
264 sExpression
= aFormula
.getExpression();
265 // as fallback, if the below matching does not succeed, assume
266 // the whole expression is the LHS
270 // the data field (or expression) to which our control is bound
271 const ReportFormula
aFieldContentFormula( m_rAction
.getDataField() );
272 const OUString
sUnprefixedFieldContent( aFieldContentFormula
.getBracketedFieldOrExpression() );
274 // check whether one of the Field Value Expression Factories recognizes the expression
275 for (const auto& [rOperation
, rxConditionalExpression
] : m_aConditionalExpressions
)
277 if ( rxConditionalExpression
->matchExpression( sExpression
, sUnprefixedFieldContent
, sLHS
, sRHS
) )
279 eType
= eFieldValueComparison
;
280 eOperation
= rOperation
;
287 m_xConditionType
->set_active(static_cast<sal_uInt16
>(eType
));
288 m_xOperationList
->set_active(static_cast<sal_uInt16
>(eOperation
));
289 m_xCondLHS
->set_text( sLHS
);
290 m_xCondRHS
->set_text( sRHS
);
293 impl_layoutOperands();
297 void Condition::setCondition( const uno::Reference
< report::XFormatCondition
>& _rxCondition
)
299 OSL_PRECOND( _rxCondition
.is(), "Condition::setCondition: empty condition object!" );
300 if ( !_rxCondition
.is() )
303 OUString sConditionFormula
;
306 if ( _rxCondition
.is() )
307 sConditionFormula
= _rxCondition
->getFormula();
309 catch( const Exception
& )
311 DBG_UNHANDLED_EXCEPTION("reportdesign");
313 impl_setCondition( sConditionFormula
);
314 updateToolbar( _rxCondition
.get() );
318 void Condition::updateToolbar(const uno::Reference
< report::XReportControlFormat
>& _xReportControlFormat
)
320 OString aItems
[] = { "bold", "italic", "underline", "fontdialog" };
322 OSL_ENSURE(_xReportControlFormat
.is(),"XReportControlFormat is NULL!");
323 if ( _xReportControlFormat
.is() )
325 for (size_t j
= 0; j
< SAL_N_ELEMENTS(aItems
); ++j
)
327 m_xActions
->set_item_active(aItems
[j
], OReportController::isFormatCommandEnabled(mapToolbarItemToSlotId(aItems
[j
]),
328 _xReportControlFormat
));
333 vcl::Font
aBaseFont( Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetAppFont() );
334 SvxFont
aFont( VCLUnoHelper::CreateFont( _xReportControlFormat
->getFontDescriptor(), aBaseFont
) );
335 aFont
.SetFontHeight(OutputDevice::LogicToLogic(Size(0, aFont
.GetFontHeight()), MapMode(MapUnit::MapPoint
), MapMode(MapUnit::MapTwip
)).Height());
336 aFont
.SetEmphasisMark( static_cast< FontEmphasisMark
>( _xReportControlFormat
->getControlTextEmphasis() ) );
337 aFont
.SetRelief( static_cast< FontRelief
>( _xReportControlFormat
->getCharRelief() ) );
338 aFont
.SetColor( Color(_xReportControlFormat
->getCharColor()) );
339 m_aPreview
.SetFont( aFont
, aFont
, aFont
);
340 m_aPreview
.SetBackColor( Color(_xReportControlFormat
->getControlBackground()) );
341 m_aPreview
.SetTextLineColor( Color( _xReportControlFormat
->getCharUnderlineColor() ) );
343 catch( const Exception
& )
345 DBG_UNHANDLED_EXCEPTION("reportdesign");
350 void Condition::fillFormatCondition(const uno::Reference
< report::XFormatCondition
>& _xCondition
)
352 const ConditionType
eType( impl_getCurrentConditionType() );
353 const ComparisonOperation
eOperation( impl_getCurrentComparisonOperation() );
355 const OUString
sLHS( m_xCondLHS
->get_text() );
356 const OUString
sRHS( m_xCondRHS
->get_text() );
358 OUString
sUndecoratedFormula( sLHS
);
360 if ( eType
== eFieldValueComparison
)
362 ReportFormula
aFieldContentFormula( m_rAction
.getDataField() );
363 OUString
sUnprefixedFieldContent( aFieldContentFormula
.getBracketedFieldOrExpression() );
365 PConditionalExpression
pFactory( m_aConditionalExpressions
[ eOperation
] );
366 sUndecoratedFormula
= pFactory
->assembleExpression( sUnprefixedFieldContent
, sLHS
, sRHS
);
369 ReportFormula
aFormula( ReportFormula::Expression
, sUndecoratedFormula
);
370 _xCondition
->setFormula( aFormula
.getCompleteFormula() );
373 void Condition::setConditionIndex( size_t _nCondIndex
, size_t _nCondCount
)
375 m_nCondIndex
= _nCondIndex
;
376 OUString
sHeader( RptResId( STR_NUMBERED_CONDITION
) );
377 sHeader
= sHeader
.replaceFirst( "$number$", OUString::number( _nCondIndex
+ 1) );
378 m_xHeader
->set_label( sHeader
);
380 m_xMoveUp
->set_sensitive(_nCondIndex
> 0);
381 OSL_PRECOND( _nCondCount
> 0, "Condition::setConditionIndex: having no conditions at all is nonsense!" );
382 m_xMoveDown
->set_sensitive(_nCondIndex
< _nCondCount
- 1);
385 bool Condition::isEmpty() const
387 return m_xCondLHS
->get_text().isEmpty();
393 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */