Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / condformat / condformatdlg.cxx
blob907c1b6294728fcb45fcd73a8630475ce9e3d432
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "condformatdlg.hxx"
11 #include "condformatdlg.hrc"
13 #include <vcl/vclevent.hxx>
14 #include <svl/style.hxx>
15 #include <sfx2/dispatch.hxx>
16 #include <svl/stritem.hxx>
17 #include <svl/intitem.hxx>
18 #include <svx/xtable.hxx>
19 #include <svx/drawitem.hxx>
20 #include <vcl/msgbox.hxx>
22 #include "anyrefdg.hxx"
23 #include "document.hxx"
24 #include "conditio.hxx"
25 #include "stlpool.hxx"
26 #include "tabvwsh.hxx"
27 #include "colorscale.hxx"
28 #include "colorformat.hxx"
29 #include "reffact.hxx"
30 #include "docsh.hxx"
31 #include "docfunc.hxx"
32 #include "condformatdlgentry.hxx"
34 #include "globstr.hrc"
36 ScCondFormatList::ScCondFormatList(Window* pParent, const ResId& rResId, ScDocument* pDoc, const ScConditionalFormat* pFormat,
37 const ScRangeList& rRanges, const ScAddress& rPos, condformat::dialog::ScCondFormatDialogType eType):
38 Control(pParent, rResId),
39 mbHasScrollBar(false),
40 mpScrollBar(new ScrollBar(this, WB_VERT )),
41 mpDoc(pDoc),
42 maPos(rPos),
43 maRanges(rRanges)
45 mpScrollBar->SetScrollHdl( LINK( this, ScCondFormatList, ScrollHdl ) );
46 mpScrollBar->EnableDrag();
48 if(pFormat)
50 size_t nCount = pFormat->size();
51 for (size_t nIndex = 0; nIndex < nCount; ++nIndex)
53 const ScFormatEntry* pEntry = pFormat->GetEntry(nIndex);
54 switch(pEntry->GetType())
56 case condformat::CONDITION:
58 const ScCondFormatEntry* pConditionEntry = static_cast<const ScCondFormatEntry*>( pEntry );
59 if(pConditionEntry->GetOperation() != SC_COND_DIRECT)
60 maEntries.push_back(new ScConditionFrmtEntry( this, mpDoc, maPos, pConditionEntry ) );
61 else
62 maEntries.push_back(new ScFormulaFrmtEntry( this, mpDoc, maPos, pConditionEntry ) );
65 break;
66 case condformat::COLORSCALE:
68 const ScColorScaleFormat* pColorScale = static_cast<const ScColorScaleFormat*>( pEntry );
69 if( pColorScale->size() == 2 )
70 maEntries.push_back(new ScColorScale2FrmtEntry( this, mpDoc, maPos, pColorScale ) );
71 else
72 maEntries.push_back(new ScColorScale3FrmtEntry( this, mpDoc, maPos, pColorScale ) );
74 break;
75 case condformat::DATABAR:
76 maEntries.push_back(new ScDataBarFrmtEntry( this, mpDoc, maPos, static_cast<const ScDataBarFormat*>( pEntry ) ) );
77 break;
78 case condformat::ICONSET:
79 maEntries.push_back(new ScIconSetFrmtEntry( this, mpDoc, maPos, static_cast<const ScIconSetFormat*>( pEntry ) ) );
80 break;
81 case condformat::DATE:
82 maEntries.push_back(new ScDateFrmtEntry( this, mpDoc, static_cast<const ScCondDateFormatEntry*>( pEntry ) ) );
83 break;
86 if(nCount)
87 EntrySelectHdl(&maEntries[0]);
89 else
91 switch(eType)
93 case condformat::dialog::CONDITION:
94 maEntries.push_back(new ScConditionFrmtEntry( this, mpDoc, maPos ));
95 break;
96 case condformat::dialog::COLORSCALE:
97 maEntries.push_back(new ScColorScale3FrmtEntry( this, mpDoc, maPos ));
98 break;
99 case condformat::dialog::DATABAR:
100 maEntries.push_back(new ScDataBarFrmtEntry( this, mpDoc, maPos ));
101 break;
102 case condformat::dialog::ICONSET:
103 maEntries.push_back(new ScIconSetFrmtEntry( this, mpDoc, maPos ));
104 break;
105 case condformat::dialog::DATE:
106 maEntries.push_back(new ScDateFrmtEntry( this, mpDoc ));
107 break;
108 case condformat::dialog::NONE:
109 break;
112 RecalcAll();
113 if (!maEntries.empty())
114 maEntries.begin()->SetActive();
116 RecalcAll();
119 ScConditionalFormat* ScCondFormatList::GetConditionalFormat() const
121 if(maEntries.empty())
122 return NULL;
124 ScConditionalFormat* pFormat = new ScConditionalFormat(0, mpDoc);
125 for(EntryContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
127 ScFormatEntry* pEntry = itr->GetEntry();
128 if(pEntry)
129 pFormat->AddEntry(pEntry);
132 pFormat->AddRange(maRanges);
134 return pFormat;
137 void ScCondFormatList::RecalcAll()
139 sal_Int32 nTotalHeight = 0;
140 sal_Int32 nIndex = 1;
141 for(EntryContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
143 nTotalHeight += itr->GetSizePixel().Height();
144 itr->SetIndex( nIndex );
145 ++nIndex;
148 Size aCtrlSize = GetOutputSize();
149 long nSrcBarSize = GetSettings().GetStyleSettings().GetScrollBarSize();
150 if(nTotalHeight > GetSizePixel().Height())
152 mbHasScrollBar = true;
153 mpScrollBar->SetPosSizePixel(Point(aCtrlSize.Width() -nSrcBarSize, 0),
154 Size(nSrcBarSize, aCtrlSize.Height()) );
155 mpScrollBar->SetRangeMax(nTotalHeight);
156 mpScrollBar->SetVisibleSize(aCtrlSize.Height());
157 mpScrollBar->Show();
159 else
161 mbHasScrollBar = false;
162 mpScrollBar->Hide();
165 Point aPoint(0,-1*mpScrollBar->GetThumbPos());
166 for(EntryContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
168 itr->SetPosPixel(aPoint);
169 Size aSize = itr->GetSizePixel();
170 if(mbHasScrollBar)
171 aSize.Width() = aCtrlSize.Width() - nSrcBarSize;
172 else
173 aSize.Width() = aCtrlSize.Width();
174 itr->SetSizePixel(aSize);
176 aPoint.Y() += itr->GetSizePixel().Height();
180 void ScCondFormatList::DoScroll(long nDelta)
182 Point aNewPoint = mpScrollBar->GetPosPixel();
183 Rectangle aRect(Point(), GetOutputSize());
184 aRect.Right() -= mpScrollBar->GetSizePixel().Width();
185 Scroll( 0, -nDelta, aRect );
186 mpScrollBar->SetPosPixel(aNewPoint);
189 IMPL_LINK(ScCondFormatList, ColFormatTypeHdl, ListBox*, pBox)
191 EntryContainer::iterator itr = maEntries.begin();
192 for(; itr != maEntries.end(); ++itr)
194 if(itr->IsSelected())
195 break;
197 if(itr == maEntries.end())
198 return 0;
200 sal_Int32 nPos = pBox->GetSelectEntryPos();
201 switch(nPos)
203 case 0:
204 if(itr->GetType() == condformat::entry::COLORSCALE2)
205 return 0;
207 maEntries.replace( itr, new ScColorScale2FrmtEntry( this, mpDoc, maPos ) );
208 break;
209 case 1:
210 if(itr->GetType() == condformat::entry::COLORSCALE3)
211 return 0;
213 maEntries.replace( itr, new ScColorScale3FrmtEntry( this, mpDoc, maPos ) );
214 break;
215 case 2:
216 if(itr->GetType() == condformat::entry::DATABAR)
217 return 0;
219 maEntries.replace( itr, new ScDataBarFrmtEntry( this, mpDoc, maPos ) );
220 break;
221 case 3:
222 if(itr->GetType() == condformat::entry::ICONSET)
223 return 0;
225 maEntries.replace( itr, new ScIconSetFrmtEntry( this, mpDoc, maPos ) );
226 break;
227 default:
228 break;
230 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
231 itr->SetActive();
232 RecalcAll();
233 return 0;
236 IMPL_LINK(ScCondFormatList, TypeListHdl, ListBox*, pBox)
238 EntryContainer::iterator itr = maEntries.begin();
239 for(; itr != maEntries.end(); ++itr)
241 if(itr->IsSelected())
242 break;
244 if(itr == maEntries.end())
245 return 0;;
247 sal_Int32 nPos = pBox->GetSelectEntryPos();
248 switch(nPos)
250 case 0:
251 switch(itr->GetType())
253 case condformat::entry::FORMULA:
254 case condformat::entry::CONDITION:
255 case condformat::entry::DATE:
256 break;
257 case condformat::entry::COLORSCALE2:
258 case condformat::entry::COLORSCALE3:
259 case condformat::entry::DATABAR:
260 case condformat::entry::ICONSET:
261 return 0;
263 maEntries.replace( itr, new ScColorScale3FrmtEntry(this, mpDoc, maPos));
264 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
265 itr->SetActive();
266 break;
267 case 1:
268 if(itr->GetType() == condformat::entry::CONDITION)
269 return 0;
271 maEntries.replace( itr, new ScConditionFrmtEntry(this, mpDoc, maPos));
272 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
273 itr->SetActive();
274 break;
275 case 2:
276 if(itr->GetType() == condformat::entry::FORMULA)
277 return 0;
279 maEntries.replace( itr, new ScFormulaFrmtEntry(this, mpDoc, maPos));
280 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
281 itr->SetActive();
282 break;
283 case 3:
284 if(itr->GetType() == condformat::entry::DATE)
285 return 0;
287 maEntries.replace( itr, new ScDateFrmtEntry( this, mpDoc ));
288 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
289 itr->SetActive();
290 break;
293 RecalcAll();
294 return 0;
297 IMPL_LINK_NOARG( ScCondFormatList, AddBtnHdl )
299 ScCondFrmtEntry* pNewEntry = new ScConditionFrmtEntry(this, mpDoc, maPos);
300 maEntries.push_back( pNewEntry );
301 for(EntryContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
303 itr->SetInactive();
305 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
306 pNewEntry->SetActive();
307 RecalcAll();
308 return 0;
311 IMPL_LINK_NOARG( ScCondFormatList, RemoveBtnHdl )
313 for(EntryContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
315 if(itr->IsSelected())
317 maEntries.erase(itr);
318 break;
321 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
322 RecalcAll();
323 return 0;
326 IMPL_LINK( ScCondFormatList, EntrySelectHdl, ScCondFrmtEntry*, pEntry )
328 if(pEntry->IsSelected())
329 return 0;
331 //A child has focus, but we will hide that, so regrab to whatever new thing gets
332 //shown instead of leaving it stuck in the inaccessible hidden element
333 bool bReGrabFocus = HasChildPathFocus();
334 for(EntryContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
336 itr->SetInactive();
338 static_cast<ScCondFormatDlg*>(GetParent())->InvalidateRefData();
339 pEntry->SetActive();
340 RecalcAll();
341 if (bReGrabFocus)
342 GrabFocus();
343 return 0;
346 IMPL_LINK_NOARG( ScCondFormatList, ScrollHdl )
348 DoScroll(mpScrollBar->GetDelta());
349 return 0;
352 //---------------------------------------------------
353 //ScCondFormatDlg
354 //---------------------------------------------------
356 ScCondFormatDlg::ScCondFormatDlg(Window* pParent, ScDocument* pDoc, const ScConditionalFormat* pFormat, const ScRangeList& rRange,
357 const ScAddress& rPos, condformat::dialog::ScCondFormatDialogType eType):
358 ScAnyRefModalDlg(pParent, ScResId(RID_SCDLG_CONDFORMAT) ),
359 maBtnAdd( this, ScResId( BTN_ADD ) ),
360 maBtnRemove( this, ScResId( BTN_REMOVE ) ),
361 maFtRange( this, ScResId( FT_RANGE ) ),
362 maEdRange( this, this, &maFtRange, ScResId( ED_RANGE ) ),
363 maRbRange( this, ScResId( RB_RANGE ), &maEdRange, this ),
364 maBtnOk( this, ScResId( BTN_OK ) ),
365 maBtnCancel( this, ScResId( BTN_CANCEL ) ),
366 maCondFormList( this, ScResId( CTRL_LIST ), pDoc, pFormat, rRange, rPos, eType ),
367 maPos(rPos),
368 mpDoc(pDoc),
369 mpLastEdit(NULL)
371 OUStringBuffer aTitle( GetText() );
372 aTitle.append(OUString(" "));
373 OUString aRangeString;
374 rRange.Format(aRangeString, SCA_VALID, pDoc, pDoc->GetAddressConvention());
375 aTitle.append(aRangeString);
376 SetText(aTitle.makeStringAndClear());
377 maBtnAdd.SetClickHdl( LINK( &maCondFormList, ScCondFormatList, AddBtnHdl ) );
378 maBtnRemove.SetClickHdl( LINK( &maCondFormList, ScCondFormatList, RemoveBtnHdl ) );
379 maEdRange.SetModifyHdl( LINK( this, ScCondFormatDlg, EdRangeModifyHdl ) );
380 maEdRange.SetGetFocusHdl( LINK( this, ScCondFormatDlg, RangeGetFocusHdl ) );
381 maEdRange.SetLoseFocusHdl( LINK( this, ScCondFormatDlg, RangeLoseFocusHdl ) );
382 FreeResource();
384 maEdRange.SetText(aRangeString);
386 SC_MOD()->PushNewAnyRefDlg(this);
389 ScCondFormatDlg::~ScCondFormatDlg()
391 SC_MOD()->PopAnyRefDlg();
394 void ScCondFormatDlg::SetActive()
396 if(mpLastEdit)
397 mpLastEdit->GrabFocus();
398 else
399 maEdRange.GrabFocus();
401 RefInputDone();
404 void ScCondFormatDlg::RefInputDone( sal_Bool bForced )
406 ScAnyRefModalDlg::RefInputDone(bForced);
409 sal_Bool ScCondFormatDlg::IsTableLocked() const
411 if(mpLastEdit && mpLastEdit != &maEdRange)
412 return sal_False;
414 return sal_True;
417 sal_Bool ScCondFormatDlg::IsRefInputMode() const
419 return maEdRange.IsEnabled();
422 #define ABS_SREF SCA_VALID \
423 | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE
424 #define ABS_DREF ABS_SREF \
425 | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE | SCA_TAB2_ABSOLUTE
426 #define ABS_DREF3D ABS_DREF | SCA_TAB_3D
428 void ScCondFormatDlg::SetReference(const ScRange& rRef, ScDocument*)
430 formula::RefEdit* pEdit = mpLastEdit;
431 if(!mpLastEdit)
432 pEdit = &maEdRange;
434 if( pEdit->IsEnabled() )
436 if(rRef.aStart != rRef.aEnd)
437 RefInputStart(pEdit);
439 sal_uInt16 n = 0;
440 if(mpLastEdit && mpLastEdit != &maEdRange)
441 n = ABS_DREF3D;
442 else
443 n = ABS_DREF;
445 OUString aRefStr(rRef.Format(n, mpDoc, ScAddress::Details(mpDoc->GetAddressConvention(), 0, 0)));
446 pEdit->SetRefString( aRefStr );
450 ScConditionalFormat* ScCondFormatDlg::GetConditionalFormat() const
452 OUString aRangeStr = maEdRange.GetText();
453 if(aRangeStr.isEmpty())
454 return NULL;
456 ScRangeList aRange;
457 sal_uInt16 nFlags = aRange.Parse(aRangeStr, mpDoc, SCA_VALID, mpDoc->GetAddressConvention(), maPos.Tab());
458 ScConditionalFormat* pFormat = maCondFormList.GetConditionalFormat();
460 if(nFlags & SCA_VALID && !aRange.empty() && pFormat)
461 pFormat->AddRange(aRange);
462 else
464 delete pFormat;
465 pFormat = NULL;
468 return pFormat;
471 void ScCondFormatDlg::InvalidateRefData()
473 mpLastEdit = NULL;
476 IMPL_LINK( ScCondFormatDlg, EdRangeModifyHdl, Edit*, pEdit )
478 OUString aRangeStr = pEdit->GetText();
479 ScRangeList aRange;
480 sal_uInt16 nFlags = aRange.Parse(aRangeStr, mpDoc, SCA_VALID, mpDoc->GetAddressConvention());
481 if(nFlags & SCA_VALID)
482 pEdit->SetControlBackground(GetSettings().GetStyleSettings().GetWindowColor());
483 else
484 pEdit->SetControlBackground(COL_LIGHTRED);
485 return 0;
488 IMPL_LINK( ScCondFormatDlg, RangeGetFocusHdl, formula::RefEdit*, pEdit )
490 mpLastEdit = pEdit;
491 return 0;
494 IMPL_LINK_NOARG( ScCondFormatDlg, RangeLoseFocusHdl )
496 //mpLastEdit = NULL;
497 return 0;
500 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */