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/builder.hxx>
26 :
27 : namespace dbaui
28 : {
29 :
30 : #define BROWSER_STANDARD_FLAGS BROWSER_COLUMNSELECTION | BROWSER_HLINESFULL | BROWSER_VLINESFULL | \
31 : BROWSER_HIDECURSOR | BROWSER_HIDESELECT | BROWSER_AUTO_HSCROLL | BROWSER_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 : : EditBrowseBox(_pParent, EBBF_SMART_TAB_TRAVEL | EBBF_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 : extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeDbaIndexFieldsControl(vcl::Window *pParent, VclBuilder::stringmap &)
107 : {
108 0 : return new IndexFieldsControl (pParent, WB_BORDER | WB_NOTABSTOP);
109 : }
110 :
111 0 : IndexFieldsControl::~IndexFieldsControl()
112 : {
113 0 : delete m_pSortingCell;
114 0 : delete m_pFieldNameCell;
115 :
116 0 : }
117 :
118 0 : bool IndexFieldsControl::SeekRow(long nRow)
119 : {
120 0 : if (!EditBrowseBox::SeekRow(nRow))
121 0 : return false;
122 :
123 0 : if (nRow < 0)
124 : {
125 0 : m_aSeekRow = m_aFields.end();
126 : }
127 : else
128 : {
129 0 : m_aSeekRow = m_aFields.begin() + nRow;
130 : OSL_ENSURE(m_aSeekRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
131 : }
132 :
133 0 : return true;
134 : }
135 :
136 0 : void IndexFieldsControl::PaintCell( OutputDevice& _rDev, const Rectangle& _rRect, sal_uInt16 _nColumnId ) const
137 : {
138 0 : Point aPos(_rRect.TopLeft());
139 0 : aPos.X() += 1;
140 :
141 0 : OUString aText = GetRowCellText(m_aSeekRow,_nColumnId);
142 0 : Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight());
143 :
144 : // clipping
145 0 : if (aPos.X() < _rRect.Right() || aPos.X() + TxtSize.Width() > _rRect.Right() ||
146 0 : aPos.Y() < _rRect.Top() || aPos.Y() + TxtSize.Height() > _rRect.Bottom())
147 0 : _rDev.SetClipRegion(vcl::Region(_rRect));
148 :
149 : // allow for a disabled control ...
150 0 : bool bEnabled = IsEnabled();
151 0 : Color aOriginalColor = _rDev.GetTextColor();
152 0 : if (!bEnabled)
153 0 : _rDev.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor());
154 :
155 : // draw the text
156 0 : _rDev.DrawText(aPos, aText);
157 :
158 : // reset the color (if necessary)
159 0 : if (!bEnabled)
160 0 : _rDev.SetTextColor(aOriginalColor);
161 :
162 0 : if (_rDev.IsClipRegion())
163 0 : _rDev.SetClipRegion();
164 0 : }
165 :
166 0 : void IndexFieldsControl::initializeFrom(const IndexFields& _rFields)
167 : {
168 : // copy the field descriptions
169 0 : m_aFields = _rFields;
170 0 : m_aSeekRow = m_aFields.end();
171 :
172 0 : SetUpdateMode(false);
173 : // remove all rows
174 0 : RowRemoved(1, GetRowCount());
175 : // insert rows for the fields
176 0 : RowInserted(GetRowCount(), m_aFields.size(), false);
177 : // insert an additional row for a new field for that index
178 0 : RowInserted(GetRowCount(), 1, false);
179 0 : SetUpdateMode(true);
180 :
181 0 : GoToRowColumnId(0, COLUMN_ID_FIELDNAME);
182 0 : }
183 :
184 0 : void IndexFieldsControl::commitTo(IndexFields& _rFields)
185 : {
186 : // do not just copy the array, we may have empty field names (which should not be copied)
187 0 : _rFields.resize(m_aFields.size());
188 0 : IndexFields::const_iterator aSource = m_aFields.begin();
189 0 : IndexFields::const_iterator aSourceEnd = m_aFields.end();
190 0 : IndexFields::iterator aDest = _rFields.begin();
191 0 : for (; aSource < aSourceEnd; ++aSource)
192 0 : if (!aSource->sFieldName.isEmpty())
193 : {
194 0 : *aDest = *aSource;
195 0 : ++aDest;
196 : }
197 :
198 0 : _rFields.resize(aDest - _rFields.begin());
199 0 : }
200 :
201 0 : sal_uInt32 IndexFieldsControl::GetTotalCellWidth(long _nRow, sal_uInt16 _nColId)
202 : {
203 0 : if (COLUMN_ID_ORDER == _nColId)
204 : {
205 0 : sal_Int32 nWidthAsc = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
206 0 : sal_Int32 nWidthDesc = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
207 : // maximum plus some additional space
208 0 : return (nWidthAsc > nWidthDesc ? nWidthAsc : nWidthDesc) + GetTextWidth(OUString('0')) * 2;
209 : }
210 0 : return EditBrowseBox::GetTotalCellWidth(_nRow, _nColId);
211 : }
212 :
213 0 : void IndexFieldsControl::Init(const Sequence< OUString >& _rAvailableFields, sal_Int32 _nMaxColumnsInIndex,bool _bAddIndexAppendix)
214 : {
215 0 : m_nMaxColumnsInIndex = _nMaxColumnsInIndex;
216 0 : m_bAddIndexAppendix = _bAddIndexAppendix;
217 :
218 0 : RemoveColumns();
219 :
220 : // for the width: both columns together should be somewhat smaller than the whole window (without the scrollbar)
221 0 : sal_Int32 nFieldNameWidth = GetSizePixel().Width();
222 :
223 0 : if ( m_bAddIndexAppendix )
224 : {
225 0 : m_sAscendingText = ModuleRes(STR_ORDER_ASCENDING);
226 0 : m_sDescendingText = ModuleRes(STR_ORDER_DESCENDING);
227 :
228 : // the "sort order" column
229 0 : OUString sColumnName = ModuleRes(STR_TAB_INDEX_SORTORDER);
230 : // the width of the order column is the maximum widths of the texts used
231 : // (the title of the column)
232 0 : sal_Int32 nSortOrderColumnWidth = GetTextWidth(sColumnName);
233 : // ("ascending" + scrollbar width)
234 0 : sal_Int32 nOther = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
235 0 : nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
236 : // ("descending" + scrollbar width)
237 0 : nOther = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
238 0 : nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
239 : // (plus some additional space)
240 0 : nSortOrderColumnWidth += GetTextWidth(OUString('0')) * 2;
241 0 : InsertDataColumn(COLUMN_ID_ORDER, sColumnName, nSortOrderColumnWidth, HIB_STDSTYLE, 1);
242 :
243 0 : m_pSortingCell = new ListBoxControl(&GetDataWindow());
244 0 : m_pSortingCell->InsertEntry(m_sAscendingText);
245 0 : m_pSortingCell->InsertEntry(m_sDescendingText);
246 0 : m_pSortingCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_SORTORDER );
247 :
248 0 : nFieldNameWidth -= nSortOrderColumnWidth;
249 : }
250 0 : StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
251 0 : nFieldNameWidth -= aSystemStyle.GetScrollBarSize();
252 0 : nFieldNameWidth -= 8;
253 : // the "field name" column
254 0 : OUString sColumnName = ModuleRes(STR_TAB_INDEX_FIELD);
255 0 : InsertDataColumn(COLUMN_ID_FIELDNAME, sColumnName, nFieldNameWidth, HIB_STDSTYLE, 0);
256 :
257 : // create the cell controllers
258 : // for the field name cell
259 0 : m_pFieldNameCell = new ListBoxControl(&GetDataWindow());
260 0 : m_pFieldNameCell->InsertEntry(OUString());
261 0 : m_pFieldNameCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_FIELD );
262 0 : const OUString* pFields = _rAvailableFields.getConstArray();
263 0 : const OUString* pFieldsEnd = pFields + _rAvailableFields.getLength();
264 0 : for (;pFields < pFieldsEnd; ++pFields)
265 0 : m_pFieldNameCell->InsertEntry(*pFields);
266 0 : }
267 :
268 0 : CellController* IndexFieldsControl::GetController(long _nRow, sal_uInt16 _nColumnId)
269 : {
270 0 : if (!IsEnabled())
271 0 : return NULL;
272 :
273 0 : IndexFields::const_iterator aRow;
274 0 : bool bNewField = !implGetFieldDesc(_nRow, aRow);
275 :
276 0 : DbaMouseDownListBoxController* pReturn = NULL;
277 0 : switch (_nColumnId)
278 : {
279 : case COLUMN_ID_ORDER:
280 0 : if (!bNewField && m_pSortingCell && !aRow->sFieldName.isEmpty())
281 0 : pReturn = new DbaMouseDownListBoxController(m_pSortingCell);
282 0 : break;
283 :
284 : case COLUMN_ID_FIELDNAME:
285 0 : pReturn = new DbaMouseDownListBoxController(m_pFieldNameCell);
286 0 : break;
287 :
288 : default:
289 : OSL_FAIL("IndexFieldsControl::GetController: invalid column id!");
290 : }
291 :
292 0 : if (pReturn)
293 0 : pReturn->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl, OnListEntrySelected));
294 :
295 0 : return pReturn;
296 : }
297 :
298 0 : bool IndexFieldsControl::implGetFieldDesc(long _nRow, IndexFields::const_iterator& _rPos)
299 : {
300 0 : _rPos = m_aFields.end();
301 0 : if ((_nRow < 0) || (_nRow >= (sal_Int32)m_aFields.size()))
302 0 : return false;
303 0 : _rPos = m_aFields.begin() + _nRow;
304 0 : return true;
305 : }
306 :
307 0 : bool IndexFieldsControl::IsModified() const
308 : {
309 0 : return EditBrowseBox::IsModified();
310 : }
311 :
312 0 : bool IndexFieldsControl::SaveModified()
313 : {
314 0 : if (!IsModified())
315 0 : return true;
316 :
317 0 : switch (GetCurColumnId())
318 : {
319 : case COLUMN_ID_FIELDNAME:
320 : {
321 0 : OUString sFieldSelected = m_pFieldNameCell->GetSelectEntry();
322 0 : bool bEmptySelected = sFieldSelected.isEmpty();
323 0 : if (isNewField())
324 : {
325 0 : if (!bEmptySelected)
326 : {
327 : // add a new field to the collection
328 0 : OIndexField aNewField;
329 0 : aNewField.sFieldName = sFieldSelected;
330 0 : m_aFields.push_back(aNewField);
331 0 : RowInserted(GetRowCount(), 1, true);
332 : }
333 : }
334 : else
335 : {
336 0 : sal_Int32 nRow = GetCurRow();
337 : OSL_ENSURE(nRow < (sal_Int32)m_aFields.size(), "IndexFieldsControl::SaveModified: invalid current row!");
338 0 : if (nRow >= 0) // may be -1 in case the control was empty
339 : {
340 : // remove the field from the selection
341 0 : IndexFields::iterator aPos = m_aFields.begin() + nRow;
342 :
343 0 : if (bEmptySelected)
344 : {
345 0 : aPos->sFieldName = "";
346 :
347 : // invalidate the row to force repaint
348 0 : Invalidate(GetRowRectPixel(nRow));
349 0 : return true;
350 : }
351 :
352 0 : if (sFieldSelected == aPos->sFieldName)
353 : // nothing changed
354 0 : return true;
355 :
356 0 : aPos->sFieldName = sFieldSelected;
357 : }
358 : }
359 :
360 0 : Invalidate(GetRowRectPixel(GetCurRow()));
361 : }
362 0 : break;
363 : case COLUMN_ID_ORDER:
364 : {
365 : OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!");
366 : // selected entry
367 0 : sal_Int32 nPos = m_pSortingCell->GetSelectEntryPos();
368 : OSL_ENSURE(LISTBOX_ENTRY_NOTFOUND != nPos, "IndexFieldsControl::SaveModified: how did you get this selection??");
369 : // adjust the sort flag in the index field description
370 0 : OIndexField& rCurrentField = m_aFields[GetCurRow()];
371 0 : rCurrentField.bSortAscending = (0 == nPos);
372 :
373 : }
374 0 : break;
375 : default:
376 : OSL_FAIL("IndexFieldsControl::SaveModified: invalid column id!");
377 : }
378 0 : return true;
379 : }
380 :
381 0 : void IndexFieldsControl::InitController(CellControllerRef& /*_rController*/, long _nRow, sal_uInt16 _nColumnId)
382 : {
383 0 : IndexFields::const_iterator aFieldDescription;
384 0 : bool bNewField = !implGetFieldDesc(_nRow, aFieldDescription);
385 :
386 0 : switch (_nColumnId)
387 : {
388 : case COLUMN_ID_FIELDNAME:
389 0 : m_pFieldNameCell->SelectEntry(bNewField ? OUString() : aFieldDescription->sFieldName);
390 0 : m_pFieldNameCell->SaveValue();
391 0 : break;
392 :
393 : case COLUMN_ID_ORDER:
394 0 : m_pSortingCell->SelectEntry(aFieldDescription->bSortAscending ? m_sAscendingText : m_sDescendingText);
395 0 : m_pSortingCell->SaveValue();
396 0 : break;
397 :
398 : default:
399 : OSL_FAIL("IndexFieldsControl::InitController: invalid column id!");
400 : }
401 0 : }
402 :
403 0 : IMPL_LINK( IndexFieldsControl, OnListEntrySelected, ListBox*, _pBox )
404 : {
405 0 : if (!_pBox->IsTravelSelect() && m_aModifyHdl.IsSet())
406 0 : m_aModifyHdl.Call(this);
407 :
408 0 : if (_pBox == m_pFieldNameCell)
409 : { // a field has been selected
410 0 : if (GetCurRow() >= GetRowCount() - 2)
411 : { // and we're in one of the last two rows
412 0 : OUString sSelectedEntry = m_pFieldNameCell->GetSelectEntry();
413 0 : sal_Int32 nCurrentRow = GetCurRow();
414 0 : sal_Int32 rowCount = GetRowCount();
415 :
416 : OSL_ENSURE(((sal_Int32)(m_aFields.size() + 1)) == rowCount, "IndexFieldsControl::OnListEntrySelected: inconsistence!");
417 :
418 0 : if (!sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 1) /*&& (!m_nMaxColumnsInIndex || rowCount < m_nMaxColumnsInIndex )*/ )
419 : { // in the last row, an non-empty string has been selected
420 : // -> insert a new row
421 0 : m_aFields.push_back(OIndexField());
422 0 : RowInserted(GetRowCount(), 1);
423 0 : Invalidate(GetRowRectPixel(nCurrentRow));
424 : }
425 0 : else if (sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 2))
426 : { // in the (last-1)th row, an empty entry has been selected
427 : // -> remove the last row
428 0 : m_aFields.erase(m_aFields.end() - 1);
429 0 : RowRemoved(GetRowCount() - 1, 1);
430 0 : Invalidate(GetRowRectPixel(nCurrentRow));
431 0 : }
432 : }
433 :
434 0 : SaveModified();
435 : }
436 0 : return 0L;
437 : }
438 0 : OUString IndexFieldsControl::GetCellText(long _nRow,sal_uInt16 nColId) const
439 : {
440 0 : IndexFields::const_iterator aRow = m_aFields.end();
441 0 : if ( _nRow >= 0 )
442 : {
443 0 : aRow = m_aFields.begin() + _nRow;
444 : OSL_ENSURE(aRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
445 : }
446 0 : return GetRowCellText(aRow,nColId);
447 : }
448 0 : OUString IndexFieldsControl::GetRowCellText(const IndexFields::const_iterator& _rRow,sal_uInt16 nColId) const
449 : {
450 0 : if (_rRow < m_aFields.end())
451 : {
452 0 : switch (nColId)
453 : {
454 : case COLUMN_ID_FIELDNAME:
455 0 : return _rRow->sFieldName;
456 : case COLUMN_ID_ORDER:
457 0 : if (_rRow->sFieldName.isEmpty())
458 0 : return OUString();
459 : else
460 0 : return _rRow->bSortAscending ? m_sAscendingText : m_sDescendingText;
461 : default:
462 : OSL_FAIL("IndexFieldsControl::GetCurrentRowCellText: invalid column id!");
463 : }
464 : }
465 0 : return OUString();
466 : }
467 0 : bool IndexFieldsControl::IsTabAllowed(bool /*bForward*/) const
468 : {
469 0 : return false;
470 : }
471 :
472 72 : } // namespace dbaui
473 :
474 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|