LibreOffice Module reportdesign (master) 1
CondFormat.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 <CondFormat.hxx>
21
22#include <strings.hxx>
23#include <strings.hrc>
24#include <core_resource.hxx>
25#include <ReportController.hxx>
26#include "Condition.hxx"
27
28#include <com/sun/star/lang/IllegalArgumentException.hpp>
29#include <o3tl/safeint.hxx>
31
33
36
37#include <algorithm>
38#include <UndoActions.hxx>
39
40
41namespace rptui
42{
43
44
45 using ::com::sun::star::uno::Reference;
46 using ::com::sun::star::uno::UNO_QUERY_THROW;
47 using ::com::sun::star::uno::UNO_QUERY;
48 using ::com::sun::star::uno::Exception;
49 using ::com::sun::star::lang::IllegalArgumentException;
50 using ::com::sun::star::uno::Sequence;
51 using ::com::sun::star::beans::PropertyValue;
52 using ::com::sun::star::uno::Any;
53
54 using namespace ::com::sun::star::report;
55
57 {
58 if (!m_bConstructed && !bFirst)
59 return;
60
61 //allow dialog to resize itself
63 if (!nCount)
64 return;
65
66 auto nHeight = m_aConditions[0]->get_preferred_size().Height();
67 size_t nVisibleConditions = ::std::min(nCount, MAX_CONDITIONS);
68 nHeight *= nVisibleConditions;
69 nHeight += 2;
70 if (nHeight != m_xScrollWindow->get_size_request().Height())
71 {
72 m_xScrollWindow->set_size_request(-1, nHeight);
73 if (!bFirst)
74 m_xDialog->resize_to_request();
75 }
76 }
77
79 weld::Window* _pParent, const Reference< XReportControlModel >& _rxFormatConditions, ::rptui::OReportController& _rController)
80 : GenericDialogController(_pParent, "modules/dbreport/ui/condformatdialog.ui", "CondFormat")
81 , m_rController(_rController)
82 , m_xFormatConditions(_rxFormatConditions)
83 , m_bConstructed(false)
84 , m_xScrollWindow(m_xBuilder->weld_scrolled_window("scrolledwindow"))
85 , m_xConditionPlayground(m_xBuilder->weld_box("condPlaygroundDrawingarea"))
86 {
87 OSL_ENSURE( m_xFormatConditions.is(), "ConditionalFormattingDialog::ConditionalFormattingDialog: ReportControlModel is NULL -> Prepare for GPF!" );
88
89 m_xCopy.set( m_xFormatConditions->createClone(), UNO_QUERY_THROW );
90
91 m_xScrollWindow->connect_vadjustment_changed(LINK(this, ConditionalFormattingDialog, OnScroll));
92
94
96
97 m_bConstructed = true;
98 }
99
101 {
102 }
103
105 {
106 sal_Int32 nIndex = 0;
107 for (const auto& rxCondition : m_aConditions)
108 {
109 rxCondition->setConditionIndex( nIndex, impl_getConditionCount() );
110 m_xConditionPlayground->reorder_child(rxCondition->get_widget(), nIndex);
111 ++nIndex;
112 }
113 }
114
116 {
117 if ( m_aConditions.empty() )
119
120 impl_setPrefHeight(false);
121
124 }
125
126 void ConditionalFormattingDialog::addCondition( size_t _nAddAfterIndex )
127 {
128 OSL_PRECOND( _nAddAfterIndex < impl_getConditionCount(), "ConditionalFormattingDialog::addCondition: illegal condition index!" );
129 impl_addCondition_nothrow( _nAddAfterIndex + 1 );
130 }
131
132
134 {
135 impl_deleteCondition_nothrow( _nCondIndex );
136 }
137
138
140 {
141 try
142 {
143 if ( _nNewCondIndex > o3tl::make_unsigned(m_xCopy->getCount()) )
144 throw IllegalArgumentException();
145
146 Reference< XFormatCondition > xCond = m_xCopy->createFormatCondition();
147 ::comphelper::copyProperties(m_xCopy, xCond);
148 m_xCopy->insertByIndex( _nNewCondIndex, Any( xCond ) );
149 auto xCon = std::make_unique<Condition>(m_xConditionPlayground.get(), m_xDialog.get(), *this, m_rController);
150 xCon->setCondition(xCond);
151 m_xConditionPlayground->reorder_child(xCon->get_widget(), _nNewCondIndex);
152 m_aConditions.insert(m_aConditions.begin() + _nNewCondIndex, std::move(xCon));
153 }
154 catch( const Exception& )
155 {
156 DBG_UNHANDLED_EXCEPTION("reportdesign");
157 }
158
160
161 impl_ensureConditionVisible( _nNewCondIndex );
162 }
163
165 {
166 OSL_PRECOND( _nCondIndex < impl_getConditionCount(),
167 "ConditionalFormattingDialog::impl_focusCondition: illegal index!" );
168
169 impl_ensureConditionVisible( _nCondIndex );
170 m_aConditions[ _nCondIndex ]->grab_focus();
171 }
172
174 {
175 OSL_PRECOND( _nCondIndex < impl_getConditionCount(),
176 "ConditionalFormattingDialog::impl_deleteCondition_nothrow: illegal index!" );
177
178 bool bLastCondition = ( impl_getConditionCount() == 1 );
179
180 bool bSetNewFocus = false;
181 size_t nNewFocusIndex( _nCondIndex );
182 try
183 {
184 if ( !bLastCondition )
185 m_xCopy->removeByIndex( _nCondIndex );
186
187 Conditions::iterator pos = m_aConditions.begin() + _nCondIndex;
188 if ( bLastCondition )
189 {
190 Reference< XFormatCondition > xFormatCondition( m_xCopy->getByIndex( 0 ), UNO_QUERY_THROW );
191 xFormatCondition->setFormula( OUString() );
192 (*pos)->setCondition( xFormatCondition );
193 }
194 else
195 {
196 bSetNewFocus = (*pos)->has_focus();
197
198 auto xMovedCondition = std::move(*pos);
199 m_aConditions.erase(pos);
200 m_xConditionPlayground->move(xMovedCondition->get_widget(), nullptr);
201 }
202
203 if ( bSetNewFocus )
204 {
205 if ( nNewFocusIndex >= impl_getConditionCount() )
206 nNewFocusIndex = impl_getConditionCount() - 1;
207 }
208 }
209 catch( const Exception& )
210 {
211 DBG_UNHANDLED_EXCEPTION("reportdesign");
212 }
213
215 if ( bSetNewFocus )
216 impl_focusCondition( nNewFocusIndex );
217 }
218
219
220 void ConditionalFormattingDialog::impl_moveCondition_nothrow( size_t _nCondIndex, bool _bMoveUp )
221 {
222 size_t nOldConditionIndex( _nCondIndex );
223 size_t nNewConditionIndex( _bMoveUp ? _nCondIndex - 1 : _nCondIndex + 1 );
224
225 // do this in two steps, so we don't become inconsistent if any of the UNO actions fails
226 Any aMovedCondition;
227 std::unique_ptr<Condition> xMovedCondition;
228 try
229 {
230 aMovedCondition = m_xCopy->getByIndex( static_cast<sal_Int32>(nOldConditionIndex) );
231 m_xCopy->removeByIndex( static_cast<sal_Int32>(nOldConditionIndex) );
232
233 Conditions::iterator aRemovePos( m_aConditions.begin() + nOldConditionIndex );
234 xMovedCondition = std::move(*aRemovePos);
235 m_aConditions.erase( aRemovePos );
236 }
237 catch( const Exception& )
238 {
239 DBG_UNHANDLED_EXCEPTION("reportdesign");
240 return;
241 }
242
243 try
244 {
245 m_xCopy->insertByIndex( static_cast<sal_Int32>(nNewConditionIndex), aMovedCondition );
246 m_aConditions.insert(m_aConditions.begin() + nNewConditionIndex, std::move(xMovedCondition));
247 }
248 catch( const Exception& )
249 {
250 DBG_UNHANDLED_EXCEPTION("reportdesign");
251 }
252
253 // at least the two swapped conditions need to know their new index
255
256 // ensure the moved condition is visible
257 impl_ensureConditionVisible( nNewConditionIndex );
258 }
259
261 {
262 size_t nFirstCondIndex( impl_getFirstVisibleConditionIndex() );
263 size_t nFocusCondIndex = impl_getFocusedConditionIndex( nFirstCondIndex );
264
265 if ( nFocusCondIndex < nFirstCondIndex )
266 impl_focusCondition( nFirstCondIndex );
267 else if ( nFocusCondIndex >= nFirstCondIndex + MAX_CONDITIONS )
268 impl_focusCondition( nFirstCondIndex + MAX_CONDITIONS - 1 );
269 }
270
272 {
273 // scrollbar visibility
274 if ( m_aConditions.size() <= MAX_CONDITIONS )
275 // normalize the position, so it can, in all situations, be used as top index
276 m_xScrollWindow->vadjustment_set_value(0);
277 }
278
280 {
281 try
282 {
283 sal_Int32 nCount = m_xCopy->getCount();
284 for ( sal_Int32 i = 0; i < nCount ; ++i )
285 {
286 auto xCon = std::make_unique<Condition>(m_xConditionPlayground.get(), m_xDialog.get(), *this, m_rController);
287 Reference< XFormatCondition > xCond( m_xCopy->getByIndex(i), UNO_QUERY );
288 m_xConditionPlayground->reorder_child(xCon->get_widget(), i);
289 xCon->setCondition(xCond);
290 xCon->updateToolbar(xCond);
291 m_aConditions.push_back(std::move(xCon));
292 }
293 }
294 catch(Exception&)
295 {
296 OSL_FAIL("Can not access format condition!");
297 }
298
300 }
301
302 void ConditionalFormattingDialog::applyCommand(size_t _nCondIndex, sal_uInt16 _nCommandId, const ::Color& rColor)
303 {
304 OSL_PRECOND( _nCommandId, "ConditionalFormattingDialog::applyCommand: illegal command id!" );
305 try
306 {
307 Reference< XReportControlFormat > xReportControlFormat( m_xCopy->getByIndex( _nCondIndex ), UNO_QUERY_THROW );
308
313 };
314
315 // we use this way to create undo actions
316 m_rController.executeUnChecked(_nCommandId,aArgs);
317 m_aConditions[ _nCondIndex ]->updateToolbar(xReportControlFormat);
318 }
319 catch( Exception& )
320 {
321 DBG_UNHANDLED_EXCEPTION("reportdesign");
322 }
323 }
324
325
327 {
328 OSL_PRECOND( _nCondIndex > 0, "ConditionalFormattingDialog::moveConditionUp: cannot move up the first condition!" );
329 if ( _nCondIndex > 0 )
330 impl_moveCondition_nothrow( _nCondIndex, true );
331 }
332
333
335 {
336 OSL_PRECOND( _nCondIndex < impl_getConditionCount(), "ConditionalFormattingDialog::moveConditionDown: cannot move down the last condition!" );
337 if ( _nCondIndex < impl_getConditionCount() )
338 impl_moveCondition_nothrow( _nCondIndex, false );
339 }
340
342 {
343 OUString sDataField;
344 try
345 {
346 sDataField = m_xFormatConditions->getDataField();
347 }
348 catch( const Exception& )
349 {
350 DBG_UNHANDLED_EXCEPTION("reportdesign");
351 }
352 return sDataField;
353 }
354
356 {
357 short nRet = GenericDialogController::run();
358 if (nRet == RET_OK)
359 {
360 const OUString sUndoAction( RptResId( RID_STR_UNDO_CONDITIONAL_FORMATTING ) );
361 const UndoContext aUndoContext( m_rController.getUndoManager(), sUndoAction );
362 try
363 {
364 sal_Int32 j(0), i(0);
365 for ( Conditions::const_iterator cond = m_aConditions.begin();
366 cond != m_aConditions.end();
367 ++cond, ++i
368 )
369 {
370 Reference< XFormatCondition > xCond( m_xCopy->getByIndex(i), UNO_QUERY_THROW );
371 (*cond)->fillFormatCondition( xCond );
372
373 if ( (*cond)->isEmpty() )
374 continue;
375
377 bool bAppend = j >= m_xFormatConditions->getCount();
378 if ( bAppend )
379 {
380 xNewCond = m_xFormatConditions->createFormatCondition();
381 m_xFormatConditions->insertByIndex( i, Any( xNewCond ) );
382 }
383 else
384 xNewCond.set( m_xFormatConditions->getByIndex(j), UNO_QUERY );
385 ++j;
386
387 ::comphelper::copyProperties(xCond, xNewCond);
388 }
389
390 for ( sal_Int32 k = m_xFormatConditions->getCount()-1; k >= j; --k )
391 m_xFormatConditions->removeByIndex(k);
392
393 ::comphelper::copyProperties( m_xCopy, m_xFormatConditions );
394 }
395 catch ( const Exception& )
396 {
397 DBG_UNHANDLED_EXCEPTION("reportdesign");
398 nRet = RET_NO;
399 }
400 }
401 return nRet;
402 }
403
405 {
406 auto nHeight = m_aConditions[0]->get_preferred_size().Height();
407 return m_xScrollWindow->vadjustment_get_value() / nHeight;
408 }
409
411 {
413 }
414
415 size_t ConditionalFormattingDialog::impl_getFocusedConditionIndex( sal_Int32 _nFallBackIfNone ) const
416 {
417 auto cond = std::find_if(m_aConditions.begin(), m_aConditions.end(),
418 [](const std::unique_ptr<Condition>& rxCondition) { return rxCondition->has_focus(); });
419 if (cond != m_aConditions.end())
420 return static_cast<size_t>(std::distance(m_aConditions.begin(), cond));
421 return _nFallBackIfNone;
422 }
423
425 {
426 OSL_PRECOND( nTopCondIndex + MAX_CONDITIONS <= impl_getConditionCount(),
427 "ConditionalFormattingDialog::impl_scrollTo: illegal index!" );
428
429 auto nHeight = m_aConditions[0]->get_preferred_size().Height();
430 m_xScrollWindow->vadjustment_set_value(nTopCondIndex * nHeight);
431 OnScroll(*m_xScrollWindow);
432 }
433
435 {
436 OSL_PRECOND( _nCondIndex < impl_getConditionCount(),
437 "ConditionalFormattingDialog::impl_ensureConditionVisible: illegal index!" );
438
439 if ( _nCondIndex < impl_getFirstVisibleConditionIndex() )
440 impl_scrollTo( _nCondIndex );
441 else if ( _nCondIndex > impl_getLastVisibleConditionIndex() )
442 impl_scrollTo( _nCondIndex - MAX_CONDITIONS + 1 );
443 }
444
445
446} // rptui
447
448
449/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ClassificationCategoriesController & m_rController
void impl_updateConditionIndicies()
tells all our Condition instances their new index
Definition: CondFormat.cxx:104
virtual void applyCommand(size_t _nCondIndex, sal_uInt16 _nCommandId, const ::Color &rColor) override
Definition: CondFormat.cxx:302
css::uno::Reference< css::report::XReportControlModel > m_xCopy
Definition: CondFormat.hxx:67
void impl_deleteCondition_nothrow(size_t _nCondIndex)
deletes the condition with the given index
Definition: CondFormat.cxx:173
virtual void moveConditionUp(size_t _nCondIndex) override
Definition: CondFormat.cxx:326
size_t impl_getFocusedConditionIndex(sal_Int32 _nFallBackIfNone) const
returns the number of the condition which has the (child path) focus
Definition: CondFormat.cxx:415
virtual void moveConditionDown(size_t _nCondIndex) override
Definition: CondFormat.cxx:334
void impl_layoutAll()
does the dialog layouting
Definition: CondFormat.cxx:271
void impl_setPrefHeight(bool bFirst)
set the preferred height of the action_area
Definition: CondFormat.cxx:56
void impl_conditionCountChanged()
called when the number of conditions has changed in any way
Definition: CondFormat.cxx:115
size_t impl_getFirstVisibleConditionIndex() const
returns the index of the first visible condition
Definition: CondFormat.cxx:404
void impl_focusCondition(size_t _nCondIndex)
focuses the condition with the given index, making it visible if necessary
Definition: CondFormat.cxx:164
virtual OUString getDataField() const override
Definition: CondFormat.cxx:341
css::uno::Reference< css::report::XReportControlModel > m_xFormatConditions
Definition: CondFormat.hxx:65
void impl_scrollTo(size_t _nTopCondIndex)
scrolls the condition with the given index to the top position
Definition: CondFormat.cxx:424
virtual void addCondition(size_t _nAddAfterIndex) override
Definition: CondFormat.cxx:126
size_t impl_getLastVisibleConditionIndex() const
returns the index of the last visible condition
Definition: CondFormat.cxx:410
ConditionalFormattingDialog(weld::Window *pParent, const css::uno::Reference< css::report::XReportControlModel > &_xHoldAlive, ::rptui::OReportController &_rController)
Definition: CondFormat.cxx:78
size_t impl_getConditionCount() const
returns the current number of conditions
Definition: CondFormat.hxx:98
void impl_initializeConditions()
initializes the conditions from m_xCopy
Definition: CondFormat.cxx:279
virtual short run() override
Definition: CondFormat.cxx:355
std::unique_ptr< weld::ScrolledWindow > m_xScrollWindow
Definition: CondFormat.hxx:71
::rptui::OReportController & m_rController
Definition: CondFormat.hxx:63
virtual void deleteCondition(size_t _nCondIndex) override
Definition: CondFormat.cxx:133
std::unique_ptr< weld::Box > m_xConditionPlayground
Definition: CondFormat.hxx:72
virtual ~ConditionalFormattingDialog() override
Definition: CondFormat.cxx:100
void impl_moveCondition_nothrow(size_t _nCondIndex, bool _bMoveUp)
moves the condition with the given index one position
Definition: CondFormat.cxx:220
void impl_addCondition_nothrow(size_t _nNewCondIndex)
adds a condition
Definition: CondFormat.cxx:139
void impl_ensureConditionVisible(size_t _nCondIndex)
ensures the condition with the given index is visible
Definition: CondFormat.cxx:434
SfxUndoManager & getUndoManager() const
std::shared_ptr< weld::Dialog > m_xDialog
OUString RptResId(TranslateId aId)
int nCount
#define DBG_UNHANDLED_EXCEPTION(...)
sal_Int32 nIndex
@ Exception
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
IMPL_LINK_NOARG(OAddFieldWindow, FocusChangeHdl, weld::Container &, void)
Definition: AddField.cxx:120
constexpr size_t MAX_CONDITIONS
Definition: CondFormat.hxx:31
constexpr OUStringLiteral REPORTCONTROLFORMAT
Definition: strings.hxx:252
constexpr OUStringLiteral PROPERTY_FONTCOLOR
Definition: strings.hxx:254
constexpr OUStringLiteral CURRENT_WINDOW
Definition: strings.hxx:253
RET_OK
RET_NO
size_t pos