1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
43 Link
<> m_aOriginalModifyHdl
;
44 Link
<> m_aAdditionalModifyHdl
;
47 DbaMouseDownListBoxController(ListBoxControl
* _pParent
)
48 :ListBoxCellController(_pParent
)
52 void SetAdditionalModifyHdl(const Link
<>& _rHdl
);
55 virtual bool WantMouseEvent() const SAL_OVERRIDE
{ return true; }
56 virtual void SetModifyHdl(const Link
<>& _rHdl
) SAL_OVERRIDE
;
59 void implCheckLinks();
60 DECL_LINK( OnMultiplexModify
, void* );
63 void DbaMouseDownListBoxController::SetAdditionalModifyHdl(const Link
<>& _rHdl
)
65 m_aAdditionalModifyHdl
= _rHdl
;
69 void DbaMouseDownListBoxController::SetModifyHdl(const Link
<>& _rHdl
)
71 m_aOriginalModifyHdl
= _rHdl
;
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
);
84 void DbaMouseDownListBoxController::implCheckLinks()
86 if (m_aAdditionalModifyHdl
.IsSet() || m_aOriginalModifyHdl
.IsSet())
87 ListBoxCellController::SetModifyHdl(LINK(this, DbaMouseDownListBoxController
, OnMultiplexModify
));
89 ListBoxCellController::SetModifyHdl(Link
<>());
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
)
109 rRet
= VclPtr
<IndexFieldsControl
>::Create(pParent
, WB_BORDER
| WB_NOTABSTOP
);
112 IndexFieldsControl::~IndexFieldsControl()
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
))
131 m_aSeekRow
= m_aFields
.end();
135 m_aSeekRow
= m_aFields
.begin() + nRow
;
136 OSL_ENSURE(m_aSeekRow
<= m_aFields
.end(), "IndexFieldsControl::SeekRow: invalid row!");
142 void IndexFieldsControl::PaintCell( OutputDevice
& _rDev
, const Rectangle
& _rRect
, sal_uInt16 _nColumnId
) const
144 Point
aPos(_rRect
.TopLeft());
147 OUString aText
= GetRowCellText(m_aSeekRow
,_nColumnId
);
148 Size
TxtSize(GetDataWindow().GetTextWidth(aText
), GetDataWindow().GetTextHeight());
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();
159 _rDev
.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor());
162 _rDev
.DrawText(aPos
, aText
);
164 // reset the color (if necessary)
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);
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);
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())
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
;
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
)
279 IndexFields::const_iterator aRow
;
280 bool bNewField
= !implGetFieldDesc(_nRow
, aRow
);
282 DbaMouseDownListBoxController
* pReturn
= NULL
;
285 case COLUMN_ID_ORDER
:
286 if (!bNewField
&& m_pSortingCell
&& !aRow
->sFieldName
.isEmpty())
287 pReturn
= new DbaMouseDownListBoxController(m_pSortingCell
);
290 case COLUMN_ID_FIELDNAME
:
291 pReturn
= new DbaMouseDownListBoxController(m_pFieldNameCell
);
295 OSL_FAIL("IndexFieldsControl::GetController: invalid column id!");
299 pReturn
->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl
, OnListEntrySelected
));
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()))
309 _rPos
= m_aFields
.begin() + _nRow
;
313 bool IndexFieldsControl::IsModified() const
315 return EditBrowseBox::IsModified();
318 bool IndexFieldsControl::SaveModified()
323 switch (GetCurColumnId())
325 case COLUMN_ID_FIELDNAME
:
327 OUString sFieldSelected
= m_pFieldNameCell
->GetSelectEntry();
328 bool bEmptySelected
= sFieldSelected
.isEmpty();
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);
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
;
351 aPos
->sFieldName
.clear();
353 // invalidate the row to force repaint
354 Invalidate(GetRowRectPixel(nRow
));
358 if (sFieldSelected
== aPos
->sFieldName
)
362 aPos
->sFieldName
= sFieldSelected
;
366 Invalidate(GetRowRectPixel(GetCurRow()));
369 case COLUMN_ID_ORDER
:
371 OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!");
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
);
382 OSL_FAIL("IndexFieldsControl::SaveModified: invalid column id!");
387 void IndexFieldsControl::InitController(CellControllerRef
& /*_rController*/, long _nRow
, sal_uInt16 _nColumnId
)
389 IndexFields::const_iterator aFieldDescription
;
390 bool bNewField
= !implGetFieldDesc(_nRow
, aFieldDescription
);
394 case COLUMN_ID_FIELDNAME
:
395 m_pFieldNameCell
->SelectEntry(bNewField
? OUString() : aFieldDescription
->sFieldName
);
396 m_pFieldNameCell
->SaveValue();
399 case COLUMN_ID_ORDER
:
400 m_pSortingCell
->SelectEntry(aFieldDescription
->bSortAscending
? m_sAscendingText
: m_sDescendingText
);
401 m_pSortingCell
->SaveValue();
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
));
444 OUString
IndexFieldsControl::GetCellText(long _nRow
,sal_uInt16 nColId
) const
446 IndexFields::const_iterator aRow
= m_aFields
.end();
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())
460 case COLUMN_ID_FIELDNAME
:
461 return _rRow
->sFieldName
;
462 case COLUMN_ID_ORDER
:
463 if (_rRow
->sFieldName
.isEmpty())
466 return _rRow
->bSortAscending
? m_sAscendingText
: m_sDescendingText
;
468 OSL_FAIL("IndexFieldsControl::GetCurrentRowCellText: invalid column id!");
473 bool IndexFieldsControl::IsTabAllowed(bool /*bForward*/) const
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */