LibreOffice Module reportdesign (master)  1
Condition.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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 <reportformula.hxx>
27 
28 #include <svx/PaletteManager.hxx>
29 #include <svx/svxids.hrc>
31 #include <vcl/svapp.hxx>
32 #include <vcl/settings.hxx>
33 
34 #include <tools/diagnose_ex.h>
35 
36 namespace rptui
37 {
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::beans;
41 
42 ConditionField::ConditionField(Condition* pParent, std::unique_ptr<weld::Entry> xSubEdit,
43  std::unique_ptr<weld::Button> xFormula)
44  : m_pParent(pParent)
45  , m_xSubEdit(std::move(xSubEdit))
46  , m_xFormula(std::move(xFormula))
47 {
48  m_xFormula->set_label("...");
49  m_xFormula->connect_clicked( LINK( this, ConditionField, OnFormula ) );
50 }
51 
53 {
54  OUString sFormula(m_xSubEdit->get_text());
55  const sal_Int32 nLen = sFormula.getLength();
56  if ( nLen )
57  {
58  ReportFormula aFormula( sFormula );
59  sFormula = aFormula.getCompleteFormula();
60  }
61  uno::Reference< awt::XWindow> xInspectorWindow = m_pParent->GetXWindow();
62  uno::Reference< beans::XPropertySet> xProp(m_pParent->getController().getRowSet(),uno::UNO_QUERY);
63  if ( rptui::openDialogFormula_nothrow( sFormula, m_pParent->getController().getContext(),xInspectorWindow,xProp ) )
64  {
65  ReportFormula aFormula( sFormula );
66  m_xSubEdit->set_text(aFormula.getUndecoratedContent());
67  }
68 }
69 
71  : mpControl(pControl)
72  , mnSlotId(nSlotId)
73 {
74 }
75 
77  [[maybe_unused]] const OUString& /*rCommand*/, const NamedColor& rNamedColor)
78 {
79  mpControl->ApplyCommand(mnSlotId, rNamedColor);
80 }
81 
82 // = Condition
84  : m_xPaletteManager(std::make_shared<PaletteManager>())
85  , m_aBackColorWrapper(this, SID_BACKGROUND_COLOR)
86  , m_aForeColorWrapper(this, SID_ATTR_CHAR_COLOR2)
87  , m_rController(_rController)
88  , m_rAction(_rAction)
89  , m_nCondIndex(0)
90  , m_pDialog(pDialog)
91  , m_xBuilder(Application::CreateBuilder(pParent, "modules/dbreport/ui/conditionwin.ui"))
92  , m_xContainer(m_xBuilder->weld_container("ConditionWin"))
93  , m_xHeader(m_xBuilder->weld_label("headerLabel"))
94  , m_xConditionType(m_xBuilder->weld_combo_box("typeCombobox"))
95  , m_xOperationList(m_xBuilder->weld_combo_box("opCombobox"))
96  , m_xOperandGlue(m_xBuilder->weld_label("andLabel"))
97  , m_xActions(m_xBuilder->weld_toolbar("formatToolbox"))
98  , m_xPreview(new weld::CustomWeld(*m_xBuilder, "previewDrawingarea", m_aPreview))
99  , m_xMoveUp(m_xBuilder->weld_button("upButton"))
100  , m_xMoveDown(m_xBuilder->weld_button("downButton"))
101  , m_xAddCondition(m_xBuilder->weld_button("addButton"))
102  , m_xRemoveCondition(m_xBuilder->weld_button("removeButton"))
103 {
104  m_xCondLHS.reset(new ConditionField(this, m_xBuilder->weld_entry("lhsEntry"), m_xBuilder->weld_button("lhsButton")));
105  m_xCondRHS.reset(new ConditionField(this, m_xBuilder->weld_entry("rhsEntry"), m_xBuilder->weld_button("rhsButton")));
106 
107  m_xCondLHS->grab_focus();
108 
109  m_xConditionType->connect_changed( LINK( this, Condition, OnTypeSelected ) );
110 
111  m_xOperationList->connect_changed( LINK( this, Condition, OnOperationSelected ) );
112 
113  m_xActions->connect_clicked(LINK(this, Condition, OnFormatAction));
114 
115  m_xMoveUp->connect_clicked( LINK( this, Condition, OnConditionAction ) );
116  m_xMoveDown->connect_clicked( LINK( this, Condition, OnConditionAction ) );
117  m_xAddCondition->connect_clicked( LINK( this, Condition, OnConditionAction ) );
118  m_xRemoveCondition->connect_clicked( LINK( this, Condition, OnConditionAction ) );
119 
120  m_xConditionType->set_active(0);
121  m_xOperationList->set_active(0);
122 
125 
126  m_xContainer->show();
127 
129 }
130 
131 sal_uInt16 Condition::mapToolbarItemToSlotId(std::string_view rItemId)
132 {
133  if (rItemId == "bold")
134  return SID_ATTR_CHAR_WEIGHT;
135  if (rItemId == "italic")
136  return SID_ATTR_CHAR_POSTURE;
137  if (rItemId == "underline")
138  return SID_ATTR_CHAR_UNDERLINE;
139  if (rItemId == "background")
140  return SID_BACKGROUND_COLOR;
141  if (rItemId == "foreground")
142  return SID_ATTR_CHAR_COLOR2;
143  if (rItemId == "fontdialog")
144  return SID_CHAR_DLG;
145  return 0;
146 }
147 
149 {
150 }
151 
153 {
154  m_xBackColorFloat.reset(new ColorWindow(
155  OUString() /*m_aCommandURL*/,
158  SID_BACKGROUND_COLOR,
159  nullptr,
160  MenuOrToolMenuButton(m_xActions.get(), "background"),
161  [this]{ return m_pDialog; },
163 
164  m_xActions->set_item_popover("background", m_xBackColorFloat->getTopLevel());
165 }
166 
168 {
169  m_xForeColorFloat.reset(new ColorWindow(
170  OUString() /*m_aCommandURL*/,
173  SID_ATTR_CHAR_COLOR2,
174  nullptr,
175  MenuOrToolMenuButton(m_xActions.get(), "foreground"),
176  [this]{ return m_pDialog; },
178 
179  m_xActions->set_item_popover("foreground", m_xForeColorFloat->getTopLevel());
180 }
181 
182 
183 IMPL_LINK(Condition, OnFormatAction, const OString&, rIdent, void)
184 {
185  ApplyCommand(mapToolbarItemToSlotId(rIdent),
186  NamedColor(COL_AUTO, "#" + COL_AUTO.AsRGBHexString()));
187 }
188 
189 IMPL_LINK(Condition, OnConditionAction, weld::Button&, rClickedButton, void)
190 {
191  if ( &rClickedButton == m_xMoveUp.get() )
192  m_rAction.moveConditionUp( getConditionIndex() );
193  else if ( &rClickedButton == m_xMoveDown.get() )
194  m_rAction.moveConditionDown( getConditionIndex() );
195  else if ( &rClickedButton == m_xAddCondition.get() )
196  m_rAction.addCondition( getConditionIndex() );
197  else if ( &rClickedButton == m_xRemoveCondition.get() )
198  m_rAction.deleteCondition( getConditionIndex() );
199 }
200 
201 void Condition::ApplyCommand( sal_uInt16 _nCommandId, const NamedColor& rNamedColor )
202 {
203  m_rAction.applyCommand( m_nCondIndex, _nCommandId, rNamedColor.first );
204 }
205 
206 IMPL_LINK_NOARG( Condition, OnTypeSelected, weld::ComboBox&, void )
207 {
208  impl_layoutOperands();
209 }
210 
211 IMPL_LINK_NOARG( Condition, OnOperationSelected, weld::ComboBox&, void )
212 {
213  impl_layoutOperands();
214 }
215 
217 {
220 
221  const bool bIsExpression = ( eType == eExpression );
222  const bool bHaveRHS =
223  ( ( eType == eFieldValueComparison )
224  && ( ( eOperation == eBetween )
225  || ( eOperation == eNotBetween )
226  )
227  );
228 
229  // the "condition type" list box
230  m_xOperationList->set_visible( !bIsExpression );
231  m_xOperandGlue->set_visible( bHaveRHS );
232  m_xCondRHS->set_visible( bHaveRHS );
233 }
234 
235 void Condition::impl_setCondition( const OUString& _rConditionFormula )
236 {
237  // determine the condition's type and comparison operation
239  ComparisonOperation eOperation( eBetween );
240 
241  // LHS and RHS, matched below
242  OUString sLHS, sRHS;
243 
244  if ( !_rConditionFormula.isEmpty() )
245  {
246  // the unprefixed expression which forms the condition
247  ReportFormula aFormula( _rConditionFormula );
248  OSL_ENSURE( aFormula.getType() == ReportFormula::Expression, "Condition::setCondition: illegal formula!" );
249  OUString sExpression;
250  if ( aFormula.getType() == ReportFormula::Expression )
251  sExpression = aFormula.getExpression();
252  // as fallback, if the below matching does not succeed, assume
253  // the whole expression is the LHS
254  eType = eExpression;
255  sLHS = sExpression;
256 
257  // the data field (or expression) to which our control is bound
258  const ReportFormula aFieldContentFormula( m_rAction.getDataField() );
259  const OUString sUnprefixedFieldContent( aFieldContentFormula.getBracketedFieldOrExpression() );
260 
261  // check whether one of the Field Value Expression Factories recognizes the expression
262  for (const auto& [rOperation, rxConditionalExpression] : m_aConditionalExpressions)
263  {
264  if ( rxConditionalExpression->matchExpression( sExpression, sUnprefixedFieldContent, sLHS, sRHS ) )
265  {
266  eType = eFieldValueComparison;
267  eOperation = rOperation;
268  break;
269  }
270  }
271  }
272 
273  // update UI
274  m_xConditionType->set_active(static_cast<sal_uInt16>(eType));
275  m_xOperationList->set_active(static_cast<sal_uInt16>(eOperation));
276  m_xCondLHS->set_text( sLHS );
277  m_xCondRHS->set_text( sRHS );
278 
279  // re-layout
281 }
282 
283 
284 void Condition::setCondition( const uno::Reference< report::XFormatCondition >& _rxCondition )
285 {
286  OSL_PRECOND( _rxCondition.is(), "Condition::setCondition: empty condition object!" );
287  if ( !_rxCondition.is() )
288  return;
289 
290  OUString sConditionFormula;
291  try
292  {
293  if ( _rxCondition.is() )
294  sConditionFormula = _rxCondition->getFormula();
295  }
296  catch( const Exception& )
297  {
298  DBG_UNHANDLED_EXCEPTION("reportdesign");
299  }
300  impl_setCondition( sConditionFormula );
301  updateToolbar( _rxCondition );
302 }
303 
304 
305 void Condition::updateToolbar(const uno::Reference< report::XReportControlFormat >& _xReportControlFormat)
306 {
307  OString aItems[] = { "bold", "italic", "underline", "fontdialog" };
308 
309  OSL_ENSURE(_xReportControlFormat.is(),"XReportControlFormat is NULL!");
310  if ( !_xReportControlFormat.is() )
311  return;
312 
313  for (size_t j = 0; j < SAL_N_ELEMENTS(aItems); ++j)
314  {
315  m_xActions->set_item_active(aItems[j], OReportController::isFormatCommandEnabled(mapToolbarItemToSlotId(aItems[j]),
316  _xReportControlFormat));
317  }
318 
319  try
320  {
321  vcl::Font aBaseFont( Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetAppFont() );
322  SvxFont aFont( VCLUnoHelper::CreateFont( _xReportControlFormat->getFontDescriptor(), aBaseFont ) );
323  aFont.SetFontHeight(OutputDevice::LogicToLogic(Size(0, aFont.GetFontHeight()), MapMode(MapUnit::MapPoint), MapMode(MapUnit::MapTwip)).Height());
324  aFont.SetEmphasisMark( static_cast< FontEmphasisMark >( _xReportControlFormat->getControlTextEmphasis() ) );
325  aFont.SetRelief( static_cast< FontRelief >( _xReportControlFormat->getCharRelief() ) );
326  aFont.SetColor( Color(ColorTransparency, _xReportControlFormat->getCharColor()) );
327  m_aPreview.SetFont( aFont, aFont, aFont );
328  m_aPreview.SetTextLineColor( Color( ColorTransparency, _xReportControlFormat->getCharUnderlineColor() ) );
329  }
330  catch( const Exception& )
331  {
332  DBG_UNHANDLED_EXCEPTION("reportdesign");
333  }
334 }
335 
336 void Condition::fillFormatCondition(const uno::Reference< report::XFormatCondition >& _xCondition)
337 {
340 
341  const OUString sLHS( m_xCondLHS->get_text() );
342  const OUString sRHS( m_xCondRHS->get_text() );
343 
344  OUString sUndecoratedFormula( sLHS );
345 
346  if ( eType == eFieldValueComparison )
347  {
348  ReportFormula aFieldContentFormula( m_rAction.getDataField() );
349  OUString sUnprefixedFieldContent( aFieldContentFormula.getBracketedFieldOrExpression() );
350 
351  PConditionalExpression pFactory( m_aConditionalExpressions[ eOperation ] );
352  sUndecoratedFormula = pFactory->assembleExpression( sUnprefixedFieldContent, sLHS, sRHS );
353  }
354 
355  ReportFormula aFormula( ReportFormula::Expression, sUndecoratedFormula );
356  _xCondition->setFormula( aFormula.getCompleteFormula() );
357 }
358 
359 void Condition::setConditionIndex( size_t _nCondIndex, size_t _nCondCount )
360 {
361  m_nCondIndex = _nCondIndex;
362  OUString sHeader( RptResId( STR_NUMBERED_CONDITION ) );
363  sHeader = sHeader.replaceFirst( "$number$", OUString::number( _nCondIndex + 1) );
364  m_xHeader->set_label( sHeader );
365 
366  m_xMoveUp->set_sensitive(_nCondIndex > 0);
367  OSL_PRECOND( _nCondCount > 0, "Condition::setConditionIndex: having no conditions at all is nonsense!" );
368  m_xMoveDown->set_sensitive(_nCondIndex < _nCondCount - 1);
369 }
370 
371 bool Condition::isEmpty() const
372 {
373  return m_xCondLHS->get_text().isEmpty();
374 }
375 
376 } // rptui
377 
378 
379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::Builder > m_xBuilder
Definition: Condition.hxx:86
std::pair< Color, OUString > NamedColor
const OUString & getUndecoratedContent() const
gets the undecorated formula content
bool isEmpty() const
determines whether the condition is actually empty
Definition: Condition.cxx:371
ComparisonOperation impl_getCurrentComparisonOperation() const
Definition: Condition.hxx:174
BindType getType() const
returns the type of the binding represented by the formula
size_t m_nCondIndex
Definition: Condition.hxx:80
std::unique_ptr< ConditionField > m_xCondLHS
Definition: Condition.hxx:91
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void impl_setCondition(const OUString &_rConditionFormula)
Definition: Condition.cxx:235
constexpr::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
std::unique_ptr< weld::Button > m_xFormula
Definition: Condition.hxx:46
static size_t getKnownConditionalExpressions(ConditionalExpressions &_out_rCondExp)
fills the given map with all ConditionalExpressions which we know
IConditionalFormatAction & m_rAction
Definition: Condition.hxx:78
OUString RptResId(std::string_view aId)
std::unique_ptr< weld::ComboBox > m_xOperationList
Definition: Condition.hxx:90
void operator()(const OUString &rCommand, const NamedColor &rColor)
Definition: Condition.cxx:76
std::shared_ptr< T > make_shared(Args &&...args)
ConditionalExpressions m_aConditionalExpressions
Definition: Condition.hxx:82
void SetBackgroundDropdownClick()
Definition: Condition.cxx:152
static OutputDevice * GetDefaultDevice()
std::unique_ptr< weld::Button > m_xMoveUp
Definition: Condition.hxx:96
Reference< XNameAccess > m_xContainer
bool openDialogFormula_nothrow(OUString &_in_out_rFormula, const css::uno::Reference< css::uno::XComponentContext > &_xContext, const css::uno::Reference< css::awt::XWindow > &_xWindow, const css::uno::Reference< css::beans::XPropertySet > &_xRowSet)
opens the formula dialog
weld::Window * m_pDialog
Definition: Condition.hxx:85
void SetTextLineColor(const Color &rColor)
std::unique_ptr< ColorWindow > m_xBackColorFloat
Definition: Condition.hxx:100
void SetFont(const SvxFont &rNormalFont, const SvxFont &rCJKFont, const SvxFont &rCTLFont)
static bool isFormatCommandEnabled(sal_uInt16 _nCommand, const css::uno::Reference< css::report::XReportControlFormat > &_xControlFormat)
returns when the command is enabled
SvxFontPrevWindow m_aPreview
Definition: Condition.hxx:84
std::unique_ptr< weld::Container > m_xContainer
Definition: Condition.hxx:87
ConditionColorWrapper(Condition *pControl, sal_uInt16 nSlotId)
Definition: Condition.cxx:70
#define SAL_N_ELEMENTS(arr)
DocumentType eType
std::shared_ptr< ConditionalExpression > PConditionalExpression
#define DBG_UNHANDLED_EXCEPTION(...)
std::unique_ptr< weld::Toolbar > m_xActions
Definition: Condition.hxx:94
void fillFormatCondition(const css::uno::Reference< css::report::XFormatCondition > &_xCondition)
fills from the control _xCondition the destination
Definition: Condition.cxx:336
virtual OUString getDataField() const =0
void setCondition(const css::uno::Reference< css::report::XFormatCondition > &_xCondition)
sets the props at the control
Definition: Condition.cxx:284
IMPL_LINK_NOARG(OAddFieldWindow, FocusChangeHdl, weld::Container &, void)
Definition: AddField.cxx:120
std::unique_ptr< weld::Button > m_xRemoveCondition
Definition: Condition.hxx:99
std::unique_ptr< weld::Label > m_xHeader
Definition: Condition.hxx:88
void updateToolbar(const css::uno::Reference< css::report::XReportControlFormat > &_xCondition)
updates the toolbar _xCondition the destination
Definition: Condition.cxx:305
ColorStatus m_aColorStatus
Definition: Condition.hxx:73
ColorTransparency
void setConditionIndex(size_t _nCondIndex, size_t _nCondCount)
tells the condition its new index within the dialog's condition array
Definition: Condition.cxx:359
ConditionField(Condition *pParent, std::unique_ptr< weld::Entry > xSubEdit, std::unique_ptr< weld::Button > xFormula)
Definition: Condition.cxx:42
IMPL_LINK(OAddFieldWindow, DragBeginHdl, bool &, rUnsetDragIcon, bool)
Definition: AddField.cxx:49
void ApplyCommand(sal_uInt16 _nCommandId, const NamedColor &rNamedColor)
forward to the parent class
Definition: Condition.cxx:201
ConditionColorWrapper m_aBackColorWrapper
Definition: Condition.hxx:74
static vcl::Font CreateFont(const css::awt::FontDescriptor &rDescr, const vcl::Font &rInitFont)
void SetForegroundDropdownClick()
Definition: Condition.cxx:167
std::unique_ptr< ConditionField > m_xCondRHS
Definition: Condition.hxx:93
Condition(weld::Container *pParent, weld::Window *pDialog, IConditionalFormatAction &rAction,::rptui::OReportController &rController)
Definition: Condition.cxx:83
std::unique_ptr< weld::Button > m_xMoveDown
Definition: Condition.hxx:97
virtual void applyCommand(size_t _nCondIndex, sal_uInt16 _nCommandId, const ::Color &rColor)=0
std::unique_ptr< weld::ComboBox > m_xConditionType
Definition: Condition.hxx:89
std::unique_ptr< weld::Label > m_xOperandGlue
Definition: Condition.hxx:92
std::shared_ptr< PaletteManager > m_xPaletteManager
Definition: Condition.hxx:72
void impl_layoutOperands()
Definition: Condition.cxx:216
const OUString & getCompleteFormula() const
returns the complete formula represented by the object
std::unique_ptr< weld::Button > m_xAddCondition
Definition: Condition.hxx:98
ConditionType impl_getCurrentConditionType() const
Definition: Condition.hxx:169
static sal_uInt16 mapToolbarItemToSlotId(std::string_view rItemId)
Definition: Condition.cxx:131
ConditionColorWrapper m_aForeColorWrapper
Definition: Condition.hxx:75
std::unique_ptr< ColorWindow > m_xForeColorFloat
Definition: Condition.hxx:101
OUString const & getExpression() const
convenience alias for getUndecoratedContent, which asserts (in a non-product build) when used on a fi...