Line data Source code
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 "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>
26 :
27 : namespace dbaui
28 : {
29 :
30 : #define BROWSER_STANDARD_FLAGS BrowserMode::COLUMNSELECTION | BrowserMode::HLINES | BrowserMode::VLINES | \
31 : BrowserMode::HIDECURSOR | BrowserMode::HIDESELECT | BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL
32 :
33 : #define COLUMN_ID_FIELDNAME 1
34 : #define COLUMN_ID_ORDER 2
35 :
36 : using namespace ::com::sun::star::uno;
37 : using namespace ::svt;
38 :
39 : // DbaMouseDownListBoxController
40 0 : class DbaMouseDownListBoxController : public ListBoxCellController
41 : {
42 : protected:
43 : Link<> m_aOriginalModifyHdl;
44 : Link<> m_aAdditionalModifyHdl;
45 :
46 : public:
47 0 : DbaMouseDownListBoxController(ListBoxControl* _pParent)
48 0 : :ListBoxCellController(_pParent)
49 : {
50 0 : }
51 :
52 : void SetAdditionalModifyHdl(const Link<>& _rHdl);
53 :
54 : protected:
55 0 : virtual bool WantMouseEvent() const SAL_OVERRIDE { return true; }
56 : virtual void SetModifyHdl(const Link<>& _rHdl) SAL_OVERRIDE;
57 :
58 : private:
59 : void implCheckLinks();
60 : DECL_LINK( OnMultiplexModify, void* );
61 : };
62 :
63 0 : void DbaMouseDownListBoxController::SetAdditionalModifyHdl(const Link<>& _rHdl)
64 : {
65 0 : m_aAdditionalModifyHdl = _rHdl;
66 0 : implCheckLinks();
67 0 : }
68 :
69 0 : void DbaMouseDownListBoxController::SetModifyHdl(const Link<>& _rHdl)
70 : {
71 0 : m_aOriginalModifyHdl = _rHdl;
72 0 : implCheckLinks();
73 0 : }
74 :
75 0 : IMPL_LINK( DbaMouseDownListBoxController, OnMultiplexModify, void*, _pArg )
76 : {
77 0 : if (m_aAdditionalModifyHdl.IsSet())
78 0 : m_aAdditionalModifyHdl.Call(_pArg);
79 0 : if (m_aOriginalModifyHdl.IsSet())
80 0 : m_aOriginalModifyHdl.Call(_pArg);
81 0 : return 0L;
82 : }
83 :
84 0 : void DbaMouseDownListBoxController::implCheckLinks()
85 : {
86 0 : if (m_aAdditionalModifyHdl.IsSet() || m_aOriginalModifyHdl.IsSet())
87 0 : ListBoxCellController::SetModifyHdl(LINK(this, DbaMouseDownListBoxController, OnMultiplexModify));
88 : else
89 0 : ListBoxCellController::SetModifyHdl(Link<>());
90 0 : }
91 :
92 : // IndexFieldsControl
93 0 : IndexFieldsControl::IndexFieldsControl( vcl::Window* _pParent, WinBits nWinStyle)
94 0 : : EditBrowseBox(_pParent, EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN, nWinStyle, BROWSER_STANDARD_FLAGS)
95 0 : , m_aSeekRow(m_aFields.end())
96 : , m_pSortingCell(NULL)
97 : , m_pFieldNameCell(NULL)
98 : , m_nMaxColumnsInIndex(0)
99 0 : , m_bAddIndexAppendix(false)
100 : {
101 :
102 0 : SetUniqueId( UID_DLGINDEX_INDEXDETAILS_BACK );
103 0 : GetDataWindow().SetUniqueId( UID_DLGINDEX_INDEXDETAILS_MAIN );
104 0 : }
105 :
106 0 : VCL_BUILDER_DECL_FACTORY(DbaIndexFieldsControl)
107 : {
108 : (void)rMap;
109 0 : rRet = VclPtr<IndexFieldsControl>::Create(pParent, WB_BORDER | WB_NOTABSTOP);
110 0 : }
111 :
112 0 : IndexFieldsControl::~IndexFieldsControl()
113 : {
114 0 : disposeOnce();
115 0 : }
116 :
117 0 : void IndexFieldsControl::dispose()
118 : {
119 0 : m_pSortingCell.disposeAndClear();
120 0 : m_pFieldNameCell.disposeAndClear();
121 0 : ::svt::EditBrowseBox::dispose();
122 0 : }
123 :
124 0 : bool IndexFieldsControl::SeekRow(long nRow)
125 : {
126 0 : if (!EditBrowseBox::SeekRow(nRow))
127 0 : return false;
128 :
129 0 : if (nRow < 0)
130 : {
131 0 : m_aSeekRow = m_aFields.end();
132 : }
133 : else
134 : {
135 0 : m_aSeekRow = m_aFields.begin() + nRow;
136 : OSL_ENSURE(m_aSeekRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
137 : }
138 :
139 0 : return true;
140 : }
141 :
142 0 : void IndexFieldsControl::PaintCell( OutputDevice& _rDev, const Rectangle& _rRect, sal_uInt16 _nColumnId ) const
143 : {
144 0 : Point aPos(_rRect.TopLeft());
145 0 : aPos.X() += 1;
146 :
147 0 : OUString aText = GetRowCellText(m_aSeekRow,_nColumnId);
148 0 : Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight());
149 :
150 : // clipping
151 0 : if (aPos.X() < _rRect.Right() || aPos.X() + TxtSize.Width() > _rRect.Right() ||
152 0 : aPos.Y() < _rRect.Top() || aPos.Y() + TxtSize.Height() > _rRect.Bottom())
153 0 : _rDev.SetClipRegion(vcl::Region(_rRect));
154 :
155 : // allow for a disabled control ...
156 0 : bool bEnabled = IsEnabled();
157 0 : Color aOriginalColor = _rDev.GetTextColor();
158 0 : if (!bEnabled)
159 0 : _rDev.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor());
160 :
161 : // draw the text
162 0 : _rDev.DrawText(aPos, aText);
163 :
164 : // reset the color (if necessary)
165 0 : if (!bEnabled)
166 0 : _rDev.SetTextColor(aOriginalColor);
167 :
168 0 : if (_rDev.IsClipRegion())
169 0 : _rDev.SetClipRegion();
170 0 : }
171 :
172 0 : void IndexFieldsControl::initializeFrom(const IndexFields& _rFields)
173 : {
174 : // copy the field descriptions
175 0 : m_aFields = _rFields;
176 0 : m_aSeekRow = m_aFields.end();
177 :
178 0 : SetUpdateMode(false);
179 : // remove all rows
180 0 : RowRemoved(1, GetRowCount());
181 : // insert rows for the fields
182 0 : RowInserted(GetRowCount(), m_aFields.size(), false);
183 : // insert an additional row for a new field for that index
184 0 : RowInserted(GetRowCount(), 1, false);
185 0 : SetUpdateMode(true);
186 :
187 0 : GoToRowColumnId(0, COLUMN_ID_FIELDNAME);
188 0 : }
189 :
190 0 : void IndexFieldsControl::commitTo(IndexFields& _rFields)
191 : {
192 : // do not just copy the array, we may have empty field names (which should not be copied)
193 0 : _rFields.resize(m_aFields.size());
194 0 : IndexFields::const_iterator aSource = m_aFields.begin();
195 0 : IndexFields::const_iterator aSourceEnd = m_aFields.end();
196 0 : IndexFields::iterator aDest = _rFields.begin();
197 0 : for (; aSource < aSourceEnd; ++aSource)
198 0 : if (!aSource->sFieldName.isEmpty())
199 : {
200 0 : *aDest = *aSource;
201 0 : ++aDest;
202 : }
203 :
204 0 : _rFields.resize(aDest - _rFields.begin());
205 0 : }
206 :
207 0 : sal_uInt32 IndexFieldsControl::GetTotalCellWidth(long _nRow, sal_uInt16 _nColId)
208 : {
209 0 : if (COLUMN_ID_ORDER == _nColId)
210 : {
211 0 : sal_Int32 nWidthAsc = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
212 0 : sal_Int32 nWidthDesc = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
213 : // maximum plus some additional space
214 0 : return (nWidthAsc > nWidthDesc ? nWidthAsc : nWidthDesc) + GetTextWidth(OUString('0')) * 2;
215 : }
216 0 : return EditBrowseBox::GetTotalCellWidth(_nRow, _nColId);
217 : }
218 :
219 0 : void IndexFieldsControl::Init(const Sequence< OUString >& _rAvailableFields, sal_Int32 _nMaxColumnsInIndex,bool _bAddIndexAppendix)
220 : {
221 0 : m_nMaxColumnsInIndex = _nMaxColumnsInIndex;
222 0 : m_bAddIndexAppendix = _bAddIndexAppendix;
223 :
224 0 : RemoveColumns();
225 :
226 : // for the width: both columns together should be somewhat smaller than the whole window (without the scrollbar)
227 0 : sal_Int32 nFieldNameWidth = GetSizePixel().Width();
228 :
229 0 : if ( m_bAddIndexAppendix )
230 : {
231 0 : m_sAscendingText = ModuleRes(STR_ORDER_ASCENDING);
232 0 : m_sDescendingText = ModuleRes(STR_ORDER_DESCENDING);
233 :
234 : // the "sort order" column
235 0 : 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 0 : sal_Int32 nSortOrderColumnWidth = GetTextWidth(sColumnName);
239 : // ("ascending" + scrollbar width)
240 0 : sal_Int32 nOther = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
241 0 : nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
242 : // ("descending" + scrollbar width)
243 0 : nOther = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
244 0 : nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
245 : // (plus some additional space)
246 0 : nSortOrderColumnWidth += GetTextWidth(OUString('0')) * 2;
247 0 : InsertDataColumn(COLUMN_ID_ORDER, sColumnName, nSortOrderColumnWidth, HeaderBarItemBits::STDSTYLE, 1);
248 :
249 0 : m_pSortingCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
250 0 : m_pSortingCell->InsertEntry(m_sAscendingText);
251 0 : m_pSortingCell->InsertEntry(m_sDescendingText);
252 0 : m_pSortingCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_SORTORDER );
253 :
254 0 : nFieldNameWidth -= nSortOrderColumnWidth;
255 : }
256 0 : StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
257 0 : nFieldNameWidth -= aSystemStyle.GetScrollBarSize();
258 0 : nFieldNameWidth -= 8;
259 : // the "field name" column
260 0 : OUString sColumnName = ModuleRes(STR_TAB_INDEX_FIELD);
261 0 : InsertDataColumn(COLUMN_ID_FIELDNAME, sColumnName, nFieldNameWidth, HeaderBarItemBits::STDSTYLE, 0);
262 :
263 : // create the cell controllers
264 : // for the field name cell
265 0 : m_pFieldNameCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
266 0 : m_pFieldNameCell->InsertEntry(OUString());
267 0 : m_pFieldNameCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_FIELD );
268 0 : const OUString* pFields = _rAvailableFields.getConstArray();
269 0 : const OUString* pFieldsEnd = pFields + _rAvailableFields.getLength();
270 0 : for (;pFields < pFieldsEnd; ++pFields)
271 0 : m_pFieldNameCell->InsertEntry(*pFields);
272 0 : }
273 :
274 0 : CellController* IndexFieldsControl::GetController(long _nRow, sal_uInt16 _nColumnId)
275 : {
276 0 : if (!IsEnabled())
277 0 : return NULL;
278 :
279 0 : IndexFields::const_iterator aRow;
280 0 : bool bNewField = !implGetFieldDesc(_nRow, aRow);
281 :
282 0 : DbaMouseDownListBoxController* pReturn = NULL;
283 0 : switch (_nColumnId)
284 : {
285 : case COLUMN_ID_ORDER:
286 0 : if (!bNewField && m_pSortingCell && !aRow->sFieldName.isEmpty())
287 0 : pReturn = new DbaMouseDownListBoxController(m_pSortingCell);
288 0 : break;
289 :
290 : case COLUMN_ID_FIELDNAME:
291 0 : pReturn = new DbaMouseDownListBoxController(m_pFieldNameCell);
292 0 : break;
293 :
294 : default:
295 : OSL_FAIL("IndexFieldsControl::GetController: invalid column id!");
296 : }
297 :
298 0 : if (pReturn)
299 0 : pReturn->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl, OnListEntrySelected));
300 :
301 0 : return pReturn;
302 : }
303 :
304 0 : bool IndexFieldsControl::implGetFieldDesc(long _nRow, IndexFields::const_iterator& _rPos)
305 : {
306 0 : _rPos = m_aFields.end();
307 0 : if ((_nRow < 0) || (_nRow >= (sal_Int32)m_aFields.size()))
308 0 : return false;
309 0 : _rPos = m_aFields.begin() + _nRow;
310 0 : return true;
311 : }
312 :
313 0 : bool IndexFieldsControl::IsModified() const
314 : {
315 0 : return EditBrowseBox::IsModified();
316 : }
317 :
318 0 : bool IndexFieldsControl::SaveModified()
319 : {
320 0 : if (!IsModified())
321 0 : return true;
322 :
323 0 : switch (GetCurColumnId())
324 : {
325 : case COLUMN_ID_FIELDNAME:
326 : {
327 0 : OUString sFieldSelected = m_pFieldNameCell->GetSelectEntry();
328 0 : bool bEmptySelected = sFieldSelected.isEmpty();
329 0 : if (isNewField())
330 : {
331 0 : if (!bEmptySelected)
332 : {
333 : // add a new field to the collection
334 0 : OIndexField aNewField;
335 0 : aNewField.sFieldName = sFieldSelected;
336 0 : m_aFields.push_back(aNewField);
337 0 : RowInserted(GetRowCount(), 1, true);
338 : }
339 : }
340 : else
341 : {
342 0 : sal_Int32 nRow = GetCurRow();
343 : OSL_ENSURE(nRow < (sal_Int32)m_aFields.size(), "IndexFieldsControl::SaveModified: invalid current row!");
344 0 : if (nRow >= 0) // may be -1 in case the control was empty
345 : {
346 : // remove the field from the selection
347 0 : IndexFields::iterator aPos = m_aFields.begin() + nRow;
348 :
349 0 : if (bEmptySelected)
350 : {
351 0 : aPos->sFieldName.clear();
352 :
353 : // invalidate the row to force repaint
354 0 : Invalidate(GetRowRectPixel(nRow));
355 0 : return true;
356 : }
357 :
358 0 : if (sFieldSelected == aPos->sFieldName)
359 : // nothing changed
360 0 : return true;
361 :
362 0 : aPos->sFieldName = sFieldSelected;
363 : }
364 : }
365 :
366 0 : Invalidate(GetRowRectPixel(GetCurRow()));
367 : }
368 0 : break;
369 : case COLUMN_ID_ORDER:
370 : {
371 : OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!");
372 : // selected entry
373 0 : 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 0 : OIndexField& rCurrentField = m_aFields[GetCurRow()];
377 0 : rCurrentField.bSortAscending = (0 == nPos);
378 :
379 : }
380 0 : break;
381 : default:
382 : OSL_FAIL("IndexFieldsControl::SaveModified: invalid column id!");
383 : }
384 0 : return true;
385 : }
386 :
387 0 : void IndexFieldsControl::InitController(CellControllerRef& /*_rController*/, long _nRow, sal_uInt16 _nColumnId)
388 : {
389 0 : IndexFields::const_iterator aFieldDescription;
390 0 : bool bNewField = !implGetFieldDesc(_nRow, aFieldDescription);
391 :
392 0 : switch (_nColumnId)
393 : {
394 : case COLUMN_ID_FIELDNAME:
395 0 : m_pFieldNameCell->SelectEntry(bNewField ? OUString() : aFieldDescription->sFieldName);
396 0 : m_pFieldNameCell->SaveValue();
397 0 : break;
398 :
399 : case COLUMN_ID_ORDER:
400 0 : m_pSortingCell->SelectEntry(aFieldDescription->bSortAscending ? m_sAscendingText : m_sDescendingText);
401 0 : m_pSortingCell->SaveValue();
402 0 : break;
403 :
404 : default:
405 : OSL_FAIL("IndexFieldsControl::InitController: invalid column id!");
406 : }
407 0 : }
408 :
409 0 : IMPL_LINK( IndexFieldsControl, OnListEntrySelected, ListBox*, _pBox )
410 : {
411 0 : if (!_pBox->IsTravelSelect() && m_aModifyHdl.IsSet())
412 0 : m_aModifyHdl.Call(this);
413 :
414 0 : if (_pBox == m_pFieldNameCell)
415 : { // a field has been selected
416 0 : if (GetCurRow() >= GetRowCount() - 2)
417 : { // and we're in one of the last two rows
418 0 : OUString sSelectedEntry = m_pFieldNameCell->GetSelectEntry();
419 0 : sal_Int32 nCurrentRow = GetCurRow();
420 0 : sal_Int32 rowCount = GetRowCount();
421 :
422 : OSL_ENSURE(((sal_Int32)(m_aFields.size() + 1)) == rowCount, "IndexFieldsControl::OnListEntrySelected: inconsistence!");
423 :
424 0 : 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 0 : m_aFields.push_back(OIndexField());
428 0 : RowInserted(GetRowCount(), 1);
429 0 : Invalidate(GetRowRectPixel(nCurrentRow));
430 : }
431 0 : 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 0 : m_aFields.erase(m_aFields.end() - 1);
435 0 : RowRemoved(GetRowCount() - 1, 1);
436 0 : Invalidate(GetRowRectPixel(nCurrentRow));
437 0 : }
438 : }
439 :
440 0 : SaveModified();
441 : }
442 0 : return 0L;
443 : }
444 0 : OUString IndexFieldsControl::GetCellText(long _nRow,sal_uInt16 nColId) const
445 : {
446 0 : IndexFields::const_iterator aRow = m_aFields.end();
447 0 : if ( _nRow >= 0 )
448 : {
449 0 : aRow = m_aFields.begin() + _nRow;
450 : OSL_ENSURE(aRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
451 : }
452 0 : return GetRowCellText(aRow,nColId);
453 : }
454 0 : OUString IndexFieldsControl::GetRowCellText(const IndexFields::const_iterator& _rRow,sal_uInt16 nColId) const
455 : {
456 0 : if (_rRow < m_aFields.end())
457 : {
458 0 : switch (nColId)
459 : {
460 : case COLUMN_ID_FIELDNAME:
461 0 : return _rRow->sFieldName;
462 : case COLUMN_ID_ORDER:
463 0 : if (_rRow->sFieldName.isEmpty())
464 0 : return OUString();
465 : else
466 0 : return _rRow->bSortAscending ? m_sAscendingText : m_sDescendingText;
467 : default:
468 : OSL_FAIL("IndexFieldsControl::GetCurrentRowCellText: invalid column id!");
469 : }
470 : }
471 0 : return OUString();
472 : }
473 0 : bool IndexFieldsControl::IsTabAllowed(bool /*bForward*/) const
474 : {
475 0 : return false;
476 : }
477 :
478 36 : } // namespace dbaui
479 :
480 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|