fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / dbaccess / source / ui / dlg / indexfieldscontrol.cxx
blobdd8f753a066de17d85c2b15eb8cf1d5c501c0b72
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/.
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 "indexfieldscontrol.hxx"
21 #include "dbu_dlg.hrc"
22 #include <osl/diagnose.h>
23 #include "dbaccess_helpid.hrc"
24 #include <vcl/settings.hxx>
25 #include <vcl/builderfactory.hxx>
27 namespace dbaui
30 #define BROWSER_STANDARD_FLAGS BrowserMode::COLUMNSELECTION | BrowserMode::HLINES | BrowserMode::VLINES | \
31 BrowserMode::HIDECURSOR | BrowserMode::HIDESELECT | BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL
33 #define COLUMN_ID_FIELDNAME 1
34 #define COLUMN_ID_ORDER 2
36 using namespace ::com::sun::star::uno;
37 using namespace ::svt;
39 // DbaMouseDownListBoxController
40 class DbaMouseDownListBoxController : public ListBoxCellController
42 protected:
43 Link<> m_aOriginalModifyHdl;
44 Link<> m_aAdditionalModifyHdl;
46 public:
47 DbaMouseDownListBoxController(ListBoxControl* _pParent)
48 :ListBoxCellController(_pParent)
52 void SetAdditionalModifyHdl(const Link<>& _rHdl);
54 protected:
55 virtual bool WantMouseEvent() const SAL_OVERRIDE { return true; }
56 virtual void SetModifyHdl(const Link<>& _rHdl) SAL_OVERRIDE;
58 private:
59 void implCheckLinks();
60 DECL_LINK( OnMultiplexModify, void* );
63 void DbaMouseDownListBoxController::SetAdditionalModifyHdl(const Link<>& _rHdl)
65 m_aAdditionalModifyHdl = _rHdl;
66 implCheckLinks();
69 void DbaMouseDownListBoxController::SetModifyHdl(const Link<>& _rHdl)
71 m_aOriginalModifyHdl = _rHdl;
72 implCheckLinks();
75 IMPL_LINK( DbaMouseDownListBoxController, OnMultiplexModify, void*, _pArg )
77 if (m_aAdditionalModifyHdl.IsSet())
78 m_aAdditionalModifyHdl.Call(_pArg);
79 if (m_aOriginalModifyHdl.IsSet())
80 m_aOriginalModifyHdl.Call(_pArg);
81 return 0L;
84 void DbaMouseDownListBoxController::implCheckLinks()
86 if (m_aAdditionalModifyHdl.IsSet() || m_aOriginalModifyHdl.IsSet())
87 ListBoxCellController::SetModifyHdl(LINK(this, DbaMouseDownListBoxController, OnMultiplexModify));
88 else
89 ListBoxCellController::SetModifyHdl(Link<>());
92 // IndexFieldsControl
93 IndexFieldsControl::IndexFieldsControl( vcl::Window* _pParent, WinBits nWinStyle)
94 : EditBrowseBox(_pParent, EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN, nWinStyle, BROWSER_STANDARD_FLAGS)
95 , m_aSeekRow(m_aFields.end())
96 , m_pSortingCell(NULL)
97 , m_pFieldNameCell(NULL)
98 , m_nMaxColumnsInIndex(0)
99 , m_bAddIndexAppendix(false)
102 SetUniqueId( UID_DLGINDEX_INDEXDETAILS_BACK );
103 GetDataWindow().SetUniqueId( UID_DLGINDEX_INDEXDETAILS_MAIN );
106 VCL_BUILDER_DECL_FACTORY(DbaIndexFieldsControl)
108 (void)rMap;
109 rRet = VclPtr<IndexFieldsControl>::Create(pParent, WB_BORDER | WB_NOTABSTOP);
112 IndexFieldsControl::~IndexFieldsControl()
114 disposeOnce();
117 void IndexFieldsControl::dispose()
119 m_pSortingCell.disposeAndClear();
120 m_pFieldNameCell.disposeAndClear();
121 ::svt::EditBrowseBox::dispose();
124 bool IndexFieldsControl::SeekRow(long nRow)
126 if (!EditBrowseBox::SeekRow(nRow))
127 return false;
129 if (nRow < 0)
131 m_aSeekRow = m_aFields.end();
133 else
135 m_aSeekRow = m_aFields.begin() + nRow;
136 OSL_ENSURE(m_aSeekRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
139 return true;
142 void IndexFieldsControl::PaintCell( OutputDevice& _rDev, const Rectangle& _rRect, sal_uInt16 _nColumnId ) const
144 Point aPos(_rRect.TopLeft());
145 aPos.X() += 1;
147 OUString aText = GetRowCellText(m_aSeekRow,_nColumnId);
148 Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight());
150 // clipping
151 if (aPos.X() < _rRect.Right() || aPos.X() + TxtSize.Width() > _rRect.Right() ||
152 aPos.Y() < _rRect.Top() || aPos.Y() + TxtSize.Height() > _rRect.Bottom())
153 _rDev.SetClipRegion(vcl::Region(_rRect));
155 // allow for a disabled control ...
156 bool bEnabled = IsEnabled();
157 Color aOriginalColor = _rDev.GetTextColor();
158 if (!bEnabled)
159 _rDev.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor());
161 // draw the text
162 _rDev.DrawText(aPos, aText);
164 // reset the color (if necessary)
165 if (!bEnabled)
166 _rDev.SetTextColor(aOriginalColor);
168 if (_rDev.IsClipRegion())
169 _rDev.SetClipRegion();
172 void IndexFieldsControl::initializeFrom(const IndexFields& _rFields)
174 // copy the field descriptions
175 m_aFields = _rFields;
176 m_aSeekRow = m_aFields.end();
178 SetUpdateMode(false);
179 // remove all rows
180 RowRemoved(1, GetRowCount());
181 // insert rows for the fields
182 RowInserted(GetRowCount(), m_aFields.size(), false);
183 // insert an additional row for a new field for that index
184 RowInserted(GetRowCount(), 1, false);
185 SetUpdateMode(true);
187 GoToRowColumnId(0, COLUMN_ID_FIELDNAME);
190 void IndexFieldsControl::commitTo(IndexFields& _rFields)
192 // do not just copy the array, we may have empty field names (which should not be copied)
193 _rFields.resize(m_aFields.size());
194 IndexFields::const_iterator aSource = m_aFields.begin();
195 IndexFields::const_iterator aSourceEnd = m_aFields.end();
196 IndexFields::iterator aDest = _rFields.begin();
197 for (; aSource < aSourceEnd; ++aSource)
198 if (!aSource->sFieldName.isEmpty())
200 *aDest = *aSource;
201 ++aDest;
204 _rFields.resize(aDest - _rFields.begin());
207 sal_uInt32 IndexFieldsControl::GetTotalCellWidth(long _nRow, sal_uInt16 _nColId)
209 if (COLUMN_ID_ORDER == _nColId)
211 sal_Int32 nWidthAsc = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
212 sal_Int32 nWidthDesc = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
213 // maximum plus some additional space
214 return (nWidthAsc > nWidthDesc ? nWidthAsc : nWidthDesc) + GetTextWidth(OUString('0')) * 2;
216 return EditBrowseBox::GetTotalCellWidth(_nRow, _nColId);
219 void IndexFieldsControl::Init(const Sequence< OUString >& _rAvailableFields, sal_Int32 _nMaxColumnsInIndex,bool _bAddIndexAppendix)
221 m_nMaxColumnsInIndex = _nMaxColumnsInIndex;
222 m_bAddIndexAppendix = _bAddIndexAppendix;
224 RemoveColumns();
226 // for the width: both columns together should be somewhat smaller than the whole window (without the scrollbar)
227 sal_Int32 nFieldNameWidth = GetSizePixel().Width();
229 if ( m_bAddIndexAppendix )
231 m_sAscendingText = ModuleRes(STR_ORDER_ASCENDING);
232 m_sDescendingText = ModuleRes(STR_ORDER_DESCENDING);
234 // the "sort order" column
235 OUString sColumnName = ModuleRes(STR_TAB_INDEX_SORTORDER);
236 // the width of the order column is the maximum widths of the texts used
237 // (the title of the column)
238 sal_Int32 nSortOrderColumnWidth = GetTextWidth(sColumnName);
239 // ("ascending" + scrollbar width)
240 sal_Int32 nOther = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
241 nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
242 // ("descending" + scrollbar width)
243 nOther = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
244 nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
245 // (plus some additional space)
246 nSortOrderColumnWidth += GetTextWidth(OUString('0')) * 2;
247 InsertDataColumn(COLUMN_ID_ORDER, sColumnName, nSortOrderColumnWidth, HeaderBarItemBits::STDSTYLE, 1);
249 m_pSortingCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
250 m_pSortingCell->InsertEntry(m_sAscendingText);
251 m_pSortingCell->InsertEntry(m_sDescendingText);
252 m_pSortingCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_SORTORDER );
254 nFieldNameWidth -= nSortOrderColumnWidth;
256 StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
257 nFieldNameWidth -= aSystemStyle.GetScrollBarSize();
258 nFieldNameWidth -= 8;
259 // the "field name" column
260 OUString sColumnName = ModuleRes(STR_TAB_INDEX_FIELD);
261 InsertDataColumn(COLUMN_ID_FIELDNAME, sColumnName, nFieldNameWidth, HeaderBarItemBits::STDSTYLE, 0);
263 // create the cell controllers
264 // for the field name cell
265 m_pFieldNameCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
266 m_pFieldNameCell->InsertEntry(OUString());
267 m_pFieldNameCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_FIELD );
268 const OUString* pFields = _rAvailableFields.getConstArray();
269 const OUString* pFieldsEnd = pFields + _rAvailableFields.getLength();
270 for (;pFields < pFieldsEnd; ++pFields)
271 m_pFieldNameCell->InsertEntry(*pFields);
274 CellController* IndexFieldsControl::GetController(long _nRow, sal_uInt16 _nColumnId)
276 if (!IsEnabled())
277 return NULL;
279 IndexFields::const_iterator aRow;
280 bool bNewField = !implGetFieldDesc(_nRow, aRow);
282 DbaMouseDownListBoxController* pReturn = NULL;
283 switch (_nColumnId)
285 case COLUMN_ID_ORDER:
286 if (!bNewField && m_pSortingCell && !aRow->sFieldName.isEmpty())
287 pReturn = new DbaMouseDownListBoxController(m_pSortingCell);
288 break;
290 case COLUMN_ID_FIELDNAME:
291 pReturn = new DbaMouseDownListBoxController(m_pFieldNameCell);
292 break;
294 default:
295 OSL_FAIL("IndexFieldsControl::GetController: invalid column id!");
298 if (pReturn)
299 pReturn->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl, OnListEntrySelected));
301 return pReturn;
304 bool IndexFieldsControl::implGetFieldDesc(long _nRow, IndexFields::const_iterator& _rPos)
306 _rPos = m_aFields.end();
307 if ((_nRow < 0) || (_nRow >= (sal_Int32)m_aFields.size()))
308 return false;
309 _rPos = m_aFields.begin() + _nRow;
310 return true;
313 bool IndexFieldsControl::IsModified() const
315 return EditBrowseBox::IsModified();
318 bool IndexFieldsControl::SaveModified()
320 if (!IsModified())
321 return true;
323 switch (GetCurColumnId())
325 case COLUMN_ID_FIELDNAME:
327 OUString sFieldSelected = m_pFieldNameCell->GetSelectEntry();
328 bool bEmptySelected = sFieldSelected.isEmpty();
329 if (isNewField())
331 if (!bEmptySelected)
333 // add a new field to the collection
334 OIndexField aNewField;
335 aNewField.sFieldName = sFieldSelected;
336 m_aFields.push_back(aNewField);
337 RowInserted(GetRowCount(), 1, true);
340 else
342 sal_Int32 nRow = GetCurRow();
343 OSL_ENSURE(nRow < (sal_Int32)m_aFields.size(), "IndexFieldsControl::SaveModified: invalid current row!");
344 if (nRow >= 0) // may be -1 in case the control was empty
346 // remove the field from the selection
347 IndexFields::iterator aPos = m_aFields.begin() + nRow;
349 if (bEmptySelected)
351 aPos->sFieldName.clear();
353 // invalidate the row to force repaint
354 Invalidate(GetRowRectPixel(nRow));
355 return true;
358 if (sFieldSelected == aPos->sFieldName)
359 // nothing changed
360 return true;
362 aPos->sFieldName = sFieldSelected;
366 Invalidate(GetRowRectPixel(GetCurRow()));
368 break;
369 case COLUMN_ID_ORDER:
371 OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!");
372 // selected entry
373 sal_Int32 nPos = m_pSortingCell->GetSelectEntryPos();
374 OSL_ENSURE(LISTBOX_ENTRY_NOTFOUND != nPos, "IndexFieldsControl::SaveModified: how did you get this selection??");
375 // adjust the sort flag in the index field description
376 OIndexField& rCurrentField = m_aFields[GetCurRow()];
377 rCurrentField.bSortAscending = (0 == nPos);
380 break;
381 default:
382 OSL_FAIL("IndexFieldsControl::SaveModified: invalid column id!");
384 return true;
387 void IndexFieldsControl::InitController(CellControllerRef& /*_rController*/, long _nRow, sal_uInt16 _nColumnId)
389 IndexFields::const_iterator aFieldDescription;
390 bool bNewField = !implGetFieldDesc(_nRow, aFieldDescription);
392 switch (_nColumnId)
394 case COLUMN_ID_FIELDNAME:
395 m_pFieldNameCell->SelectEntry(bNewField ? OUString() : aFieldDescription->sFieldName);
396 m_pFieldNameCell->SaveValue();
397 break;
399 case COLUMN_ID_ORDER:
400 m_pSortingCell->SelectEntry(aFieldDescription->bSortAscending ? m_sAscendingText : m_sDescendingText);
401 m_pSortingCell->SaveValue();
402 break;
404 default:
405 OSL_FAIL("IndexFieldsControl::InitController: invalid column id!");
409 IMPL_LINK( IndexFieldsControl, OnListEntrySelected, ListBox*, _pBox )
411 if (!_pBox->IsTravelSelect() && m_aModifyHdl.IsSet())
412 m_aModifyHdl.Call(this);
414 if (_pBox == m_pFieldNameCell)
415 { // a field has been selected
416 if (GetCurRow() >= GetRowCount() - 2)
417 { // and we're in one of the last two rows
418 OUString sSelectedEntry = m_pFieldNameCell->GetSelectEntry();
419 sal_Int32 nCurrentRow = GetCurRow();
420 sal_Int32 rowCount = GetRowCount();
422 OSL_ENSURE(((sal_Int32)(m_aFields.size() + 1)) == rowCount, "IndexFieldsControl::OnListEntrySelected: inconsistence!");
424 if (!sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 1) /*&& (!m_nMaxColumnsInIndex || rowCount < m_nMaxColumnsInIndex )*/ )
425 { // in the last row, an non-empty string has been selected
426 // -> insert a new row
427 m_aFields.push_back(OIndexField());
428 RowInserted(GetRowCount(), 1);
429 Invalidate(GetRowRectPixel(nCurrentRow));
431 else if (sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 2))
432 { // in the (last-1)th row, an empty entry has been selected
433 // -> remove the last row
434 m_aFields.erase(m_aFields.end() - 1);
435 RowRemoved(GetRowCount() - 1, 1);
436 Invalidate(GetRowRectPixel(nCurrentRow));
440 SaveModified();
442 return 0L;
444 OUString IndexFieldsControl::GetCellText(long _nRow,sal_uInt16 nColId) const
446 IndexFields::const_iterator aRow = m_aFields.end();
447 if ( _nRow >= 0 )
449 aRow = m_aFields.begin() + _nRow;
450 OSL_ENSURE(aRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
452 return GetRowCellText(aRow,nColId);
454 OUString IndexFieldsControl::GetRowCellText(const IndexFields::const_iterator& _rRow,sal_uInt16 nColId) const
456 if (_rRow < m_aFields.end())
458 switch (nColId)
460 case COLUMN_ID_FIELDNAME:
461 return _rRow->sFieldName;
462 case COLUMN_ID_ORDER:
463 if (_rRow->sFieldName.isEmpty())
464 return OUString();
465 else
466 return _rRow->bSortAscending ? m_sAscendingText : m_sDescendingText;
467 default:
468 OSL_FAIL("IndexFieldsControl::GetCurrentRowCellText: invalid column id!");
471 return OUString();
473 bool IndexFieldsControl::IsTabAllowed(bool /*bForward*/) const
475 return false;
478 } // namespace dbaui
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */