1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbui.hxx"
26
27 #ifndef _DBAUI_INDEXFIELDSCONTROL_HXX_
28 #include "indexfieldscontrol.hxx"
29 #endif
30 #ifndef _DBU_DLG_HRC_
31 #include "dbu_dlg.hrc"
32 #endif
33 #ifndef _OSL_DIAGNOSE_H_
34 #include <osl/diagnose.h>
35 #endif
36 #ifndef _DBA_DBACCESS_HELPID_HRC_
37 #include "dbaccess_helpid.hrc"
38 #endif
39
40 //......................................................................
41 namespace dbaui
42 {
43 //......................................................................
44
45 #define BROWSER_STANDARD_FLAGS BROWSER_COLUMNSELECTION | BROWSER_HLINESFULL | BROWSER_VLINESFULL | \
46 BROWSER_HIDECURSOR | BROWSER_HIDESELECT | BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL
47
48 #define COLUMN_ID_FIELDNAME 1
49 #define COLUMN_ID_ORDER 2
50
51 using namespace ::com::sun::star::uno;
52 using namespace ::svt;
53
54 //==================================================================
55 //= DbaMouseDownListBoxController
56 //==================================================================
57 class DbaMouseDownListBoxController : public ListBoxCellController
58 {
59 protected:
60 Link m_aOriginalModifyHdl;
61 Link m_aAdditionalModifyHdl;
62
63 public:
DbaMouseDownListBoxController(ListBoxControl * _pParent)64 DbaMouseDownListBoxController(ListBoxControl* _pParent)
65 :ListBoxCellController(_pParent)
66 {
67 }
68
69 void SetAdditionalModifyHdl(const Link& _rHdl);
70
71 protected:
WantMouseEvent() const72 virtual sal_Bool WantMouseEvent() const { return sal_True; }
73 virtual void SetModifyHdl(const Link& _rHdl);
74
75 private:
76 void implCheckLinks();
77 DECL_LINK( OnMultiplexModify, void* );
78 };
79
80 //------------------------------------------------------------------
SetAdditionalModifyHdl(const Link & _rHdl)81 void DbaMouseDownListBoxController::SetAdditionalModifyHdl(const Link& _rHdl)
82 {
83 m_aAdditionalModifyHdl = _rHdl;
84 implCheckLinks();
85 }
86
87 //------------------------------------------------------------------
SetModifyHdl(const Link & _rHdl)88 void DbaMouseDownListBoxController::SetModifyHdl(const Link& _rHdl)
89 {
90 m_aOriginalModifyHdl = _rHdl;
91 implCheckLinks();
92 }
93
94 //------------------------------------------------------------------
IMPL_LINK(DbaMouseDownListBoxController,OnMultiplexModify,void *,_pArg)95 IMPL_LINK( DbaMouseDownListBoxController, OnMultiplexModify, void*, _pArg )
96 {
97 if (m_aAdditionalModifyHdl.IsSet())
98 m_aAdditionalModifyHdl.Call(_pArg);
99 if (m_aOriginalModifyHdl.IsSet())
100 m_aOriginalModifyHdl.Call(_pArg);
101 return 0L;
102 }
103
104 //------------------------------------------------------------------
implCheckLinks()105 void DbaMouseDownListBoxController::implCheckLinks()
106 {
107 if (m_aAdditionalModifyHdl.IsSet() || m_aOriginalModifyHdl.IsSet())
108 ListBoxCellController::SetModifyHdl(LINK(this, DbaMouseDownListBoxController, OnMultiplexModify));
109 else
110 ListBoxCellController::SetModifyHdl(Link());
111 }
112
113 //==================================================================
114 //= IndexFieldsControl
115 //==================================================================
DBG_NAME(IndexFieldsControl)116 DBG_NAME(IndexFieldsControl)
117 //------------------------------------------------------------------
118 IndexFieldsControl::IndexFieldsControl( Window* _pParent, const ResId& _rId ,sal_Int32 _nMaxColumnsInIndex,sal_Bool _bAddIndexAppendix)
119 :EditBrowseBox(_pParent, _rId, EBBF_SMART_TAB_TRAVEL | EBBF_ACTIVATE_ON_BUTTONDOWN, BROWSER_STANDARD_FLAGS)
120 ,m_aSeekRow(m_aFields.end())
121 ,m_pSortingCell(NULL)
122 ,m_pFieldNameCell(NULL)
123 ,m_nMaxColumnsInIndex(_nMaxColumnsInIndex)
124 ,m_bAddIndexAppendix(_bAddIndexAppendix)
125 {
126 DBG_CTOR(IndexFieldsControl,NULL);
127
128 SetUniqueId( UID_DLGINDEX_INDEXDETAILS_BACK );
129 GetDataWindow().SetUniqueId( UID_DLGINDEX_INDEXDETAILS_MAIN );
130 }
131
132 //------------------------------------------------------------------
~IndexFieldsControl()133 IndexFieldsControl::~IndexFieldsControl()
134 {
135 delete m_pSortingCell;
136 delete m_pFieldNameCell;
137
138 DBG_DTOR(IndexFieldsControl,NULL);
139 }
140
141 //------------------------------------------------------------------
SeekRow(long nRow)142 sal_Bool IndexFieldsControl::SeekRow(long nRow)
143 {
144 if (!EditBrowseBox::SeekRow(nRow))
145 return sal_False;
146
147 if (nRow < 0)
148 {
149 m_aSeekRow = m_aFields.end();
150 }
151 else
152 {
153 m_aSeekRow = m_aFields.begin() + nRow;
154 OSL_ENSURE(m_aSeekRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
155 }
156
157 return sal_True;
158 }
159
160 //------------------------------------------------------------------
PaintCell(OutputDevice & _rDev,const Rectangle & _rRect,sal_uInt16 _nColumnId) const161 void IndexFieldsControl::PaintCell( OutputDevice& _rDev, const Rectangle& _rRect, sal_uInt16 _nColumnId ) const
162 {
163 Point aPos(_rRect.TopLeft());
164 aPos.X() += 1;
165
166 String aText = GetRowCellText(m_aSeekRow,_nColumnId);
167 Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight());
168
169 // clipping
170 if (aPos.X() < _rRect.Right() || aPos.X() + TxtSize.Width() > _rRect.Right() ||
171 aPos.Y() < _rRect.Top() || aPos.Y() + TxtSize.Height() > _rRect.Bottom())
172 _rDev.SetClipRegion( _rRect );
173
174 // allow for a disabled control ...
175 sal_Bool bEnabled = IsEnabled();
176 Color aOriginalColor = _rDev.GetTextColor();
177 if (!bEnabled)
178 _rDev.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor());
179
180 // draw the text
181 _rDev.DrawText(aPos, aText);
182
183 // reset the color (if necessary)
184 if (!bEnabled)
185 _rDev.SetTextColor(aOriginalColor);
186
187 if (_rDev.IsClipRegion())
188 _rDev.SetClipRegion();
189 }
190
191 //------------------------------------------------------------------
initializeFrom(const IndexFields & _rFields)192 void IndexFieldsControl::initializeFrom(const IndexFields& _rFields)
193 {
194 // copy the field descriptions
195 m_aFields = _rFields;
196 m_aSeekRow = m_aFields.end();
197
198 SetUpdateMode(sal_False);
199 // remove all rows
200 RowRemoved(1, GetRowCount());
201 // insert rows for the fields
202 RowInserted(GetRowCount(), m_aFields.size(), sal_False);
203 // insert an additional row for a new field for that index
204 // if(!m_nMaxColumnsInIndex || GetRowCount() < m_nMaxColumnsInIndex )
205 RowInserted(GetRowCount(), 1, sal_False);
206 SetUpdateMode(sal_True);
207
208 GoToRowColumnId(0, COLUMN_ID_FIELDNAME);
209 }
210
211 //------------------------------------------------------------------
commitTo(IndexFields & _rFields)212 void IndexFieldsControl::commitTo(IndexFields& _rFields)
213 {
214 // do not just copy the array, we may have empty field names (which should not be copied)
215 _rFields.resize(m_aFields.size());
216 ConstIndexFieldsIterator aSource = m_aFields.begin();
217 ConstIndexFieldsIterator aSourceEnd = m_aFields.end();
218 IndexFieldsIterator aDest = _rFields.begin();
219 for (; aSource < aSourceEnd; ++aSource)
220 if (0 != aSource->sFieldName.Len())
221 {
222 *aDest = *aSource;
223 ++aDest;
224 }
225
226 _rFields.resize(aDest - _rFields.begin());
227 }
228
229 //------------------------------------------------------------------
GetTotalCellWidth(long _nRow,sal_uInt16 _nColId)230 sal_uInt32 IndexFieldsControl::GetTotalCellWidth(long _nRow, sal_uInt16 _nColId)
231 {
232 if (COLUMN_ID_ORDER == _nColId)
233 {
234 sal_Int32 nWidthAsc = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
235 sal_Int32 nWidthDesc = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
236 // maximum plus some additional space
237 return (nWidthAsc > nWidthDesc ? nWidthAsc : nWidthDesc) + GetTextWidth('0') * 2;
238 }
239 return EditBrowseBox::GetTotalCellWidth(_nRow, _nColId);
240 }
241
242 //------------------------------------------------------------------
Init(const Sequence<::rtl::OUString> & _rAvailableFields)243 void IndexFieldsControl::Init(const Sequence< ::rtl::OUString >& _rAvailableFields)
244 {
245 RemoveColumns();
246
247 // for the width: both columns together should be somewhat smaller than the whole window (without the scrollbar)
248 sal_Int32 nFieldNameWidth = GetSizePixel().Width();
249
250 if ( m_bAddIndexAppendix )
251 {
252 m_sAscendingText = String(ModuleRes(STR_ORDER_ASCENDING));
253 m_sDescendingText = String(ModuleRes(STR_ORDER_DESCENDING));
254
255 // the "sort order" column
256 String sColumnName = String(ModuleRes(STR_TAB_INDEX_SORTORDER));
257 // the width of the order column is the maximum widths of the texts used
258 // (the title of the column)
259 sal_Int32 nSortOrderColumnWidth = GetTextWidth(sColumnName);
260 // ("ascending" + scrollbar width)
261 sal_Int32 nOther = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
262 nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
263 // ("descending" + scrollbar width)
264 nOther = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
265 nSortOrderColumnWidth = nSortOrderColumnWidth > nOther ? nSortOrderColumnWidth : nOther;
266 // (plus some additional space)
267 nSortOrderColumnWidth += GetTextWidth('0') * 2;
268 InsertDataColumn(COLUMN_ID_ORDER, sColumnName, nSortOrderColumnWidth, HIB_STDSTYLE, 1);
269
270 m_pSortingCell = new ListBoxControl(&GetDataWindow());
271 m_pSortingCell->InsertEntry(m_sAscendingText);
272 m_pSortingCell->InsertEntry(m_sDescendingText);
273 m_pSortingCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_SORTORDER );
274
275 nFieldNameWidth -= nSortOrderColumnWidth;
276 }
277 StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
278 nFieldNameWidth -= aSystemStyle.GetScrollBarSize();
279 nFieldNameWidth -= 8;
280 // the "field name" column
281 String sColumnName = String(ModuleRes(STR_TAB_INDEX_FIELD));
282 InsertDataColumn(COLUMN_ID_FIELDNAME, sColumnName, nFieldNameWidth, HIB_STDSTYLE, 0);
283
284 // create the cell controllers
285 // for the field name cell
286 m_pFieldNameCell = new ListBoxControl(&GetDataWindow());
287 m_pFieldNameCell->InsertEntry(String());
288 m_pFieldNameCell->SetHelpId( HID_DLGINDEX_INDEXDETAILS_FIELD );
289 const ::rtl::OUString* pFields = _rAvailableFields.getConstArray();
290 const ::rtl::OUString* pFieldsEnd = pFields + _rAvailableFields.getLength();
291 for (;pFields < pFieldsEnd; ++pFields)
292 m_pFieldNameCell->InsertEntry(*pFields);
293 }
294
295 //------------------------------------------------------------------
GetController(long _nRow,sal_uInt16 _nColumnId)296 CellController* IndexFieldsControl::GetController(long _nRow, sal_uInt16 _nColumnId)
297 {
298 if (!IsEnabled())
299 return NULL;
300
301 ConstIndexFieldsIterator aRow;
302 sal_Bool bNewField = !implGetFieldDesc(_nRow, aRow);
303
304 DbaMouseDownListBoxController* pReturn = NULL;
305 switch (_nColumnId)
306 {
307 case COLUMN_ID_ORDER:
308 if (!bNewField && m_pSortingCell && 0 != aRow->sFieldName.Len())
309 pReturn = new DbaMouseDownListBoxController(m_pSortingCell);
310 break;
311
312 case COLUMN_ID_FIELDNAME:
313 pReturn = new DbaMouseDownListBoxController(m_pFieldNameCell);
314 break;
315
316 default:
317 OSL_ENSURE(sal_False, "IndexFieldsControl::GetController: invalid column id!");
318 }
319
320 if (pReturn)
321 pReturn->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl, OnListEntrySelected));
322
323 return pReturn;
324 }
325
326 //------------------------------------------------------------------
implGetFieldDesc(long _nRow,ConstIndexFieldsIterator & _rPos)327 sal_Bool IndexFieldsControl::implGetFieldDesc(long _nRow, ConstIndexFieldsIterator& _rPos)
328 {
329 _rPos = m_aFields.end();
330 if ((_nRow < 0) || (_nRow >= (sal_Int32)m_aFields.size()))
331 return sal_False;
332 _rPos = m_aFields.begin() + _nRow;
333 return sal_True;
334 }
335
336 //------------------------------------------------------------------
IsModified() const337 sal_Bool IndexFieldsControl::IsModified() const
338 {
339 return EditBrowseBox::IsModified();
340 }
341
342 //------------------------------------------------------------------
SaveModified()343 sal_Bool IndexFieldsControl::SaveModified()
344 {
345 if (!IsModified())
346 return sal_True;
347
348 switch (GetCurColumnId())
349 {
350 case COLUMN_ID_FIELDNAME:
351 {
352 String sFieldSelected = m_pFieldNameCell->GetSelectEntry();
353 sal_Bool bEmptySelected = 0 == sFieldSelected.Len();
354 if (isNewField())
355 {
356 if (!bEmptySelected)
357 {
358 // add a new field to the collection
359 OIndexField aNewField;
360 aNewField.sFieldName = sFieldSelected;
361 m_aFields.push_back(aNewField);
362 RowInserted(GetRowCount(), 1, sal_True);
363 }
364 }
365 else
366 {
367 sal_Int32 nRow = GetCurRow();
368 OSL_ENSURE(nRow < (sal_Int32)m_aFields.size(), "IndexFieldsControl::SaveModified: invalid current row!");
369 if (nRow >= 0) // may be -1 in case the control was empty
370 {
371 // remove the field from the selection
372 IndexFieldsIterator aPos = m_aFields.begin() + nRow;
373
374 if (bEmptySelected)
375 {
376 aPos->sFieldName = String();
377
378 // invalidate the row to force repaint
379 Invalidate(GetRowRectPixel(nRow));
380 return sal_True;
381 }
382
383 if (sFieldSelected == aPos->sFieldName)
384 // nothing changed
385 return sal_True;
386
387 aPos->sFieldName = sFieldSelected;
388 }
389 }
390
391 Invalidate(GetRowRectPixel(GetCurRow()));
392 }
393 break;
394 case COLUMN_ID_ORDER:
395 {
396 OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!");
397 // selected entry
398 sal_uInt16 nPos = m_pSortingCell->GetSelectEntryPos();
399 OSL_ENSURE(LISTBOX_ENTRY_NOTFOUND != nPos, "IndexFieldsControl::SaveModified: how did you get this selection??");
400 // adjust the sort flag in the index field description
401 OIndexField& rCurrentField = m_aFields[GetCurRow()];
402 rCurrentField.bSortAscending = (0 == nPos);
403
404 }
405 break;
406 default:
407 OSL_ENSURE(sal_False, "IndexFieldsControl::SaveModified: invalid column id!");
408 }
409 return sal_True;
410 }
411
412 //------------------------------------------------------------------
InitController(CellControllerRef &,long _nRow,sal_uInt16 _nColumnId)413 void IndexFieldsControl::InitController(CellControllerRef& /*_rController*/, long _nRow, sal_uInt16 _nColumnId)
414 {
415 ConstIndexFieldsIterator aFieldDescription;
416 sal_Bool bNewField = !implGetFieldDesc(_nRow, aFieldDescription);
417
418 switch (_nColumnId)
419 {
420 case COLUMN_ID_FIELDNAME:
421 m_pFieldNameCell->SelectEntry(bNewField ? String() : aFieldDescription->sFieldName);
422 m_pFieldNameCell->SaveValue();
423 break;
424
425 case COLUMN_ID_ORDER:
426 m_pSortingCell->SelectEntry(aFieldDescription->bSortAscending ? m_sAscendingText : m_sDescendingText);
427 m_pSortingCell->SaveValue();
428 break;
429
430 default:
431 OSL_ENSURE(sal_False, "IndexFieldsControl::InitController: invalid column id!");
432 }
433 }
434
435 //------------------------------------------------------------------
IMPL_LINK(IndexFieldsControl,OnListEntrySelected,ListBox *,_pBox)436 IMPL_LINK( IndexFieldsControl, OnListEntrySelected, ListBox*, _pBox )
437 {
438 if (!_pBox->IsTravelSelect() && m_aModifyHdl.IsSet())
439 m_aModifyHdl.Call(this);
440
441 if (_pBox == m_pFieldNameCell)
442 { // a field has been selected
443 if (GetCurRow() >= GetRowCount() - 2)
444 { // and we're in one of the last two rows
445 String sSelectedEntry = m_pFieldNameCell->GetSelectEntry();
446 sal_Int32 nCurrentRow = GetCurRow();
447 sal_Int32 rowCount = GetRowCount();
448
449 OSL_ENSURE(((sal_Int32)(m_aFields.size() + 1)) == rowCount, "IndexFieldsControl::OnListEntrySelected: inconsistence!");
450
451 if (sSelectedEntry.Len() && (nCurrentRow == rowCount - 1) /*&& (!m_nMaxColumnsInIndex || rowCount < m_nMaxColumnsInIndex )*/ )
452 { // in the last row, an non-empty string has been selected
453 // -> insert a new row
454 m_aFields.push_back(OIndexField());
455 RowInserted(GetRowCount(), 1);
456 Invalidate(GetRowRectPixel(nCurrentRow));
457 }
458 else if (!sSelectedEntry.Len() && (nCurrentRow == rowCount - 2))
459 { // in the (last-1)th row, an empty entry has been selected
460 // -> remove the last row
461 m_aFields.erase(m_aFields.end() - 1);
462 RowRemoved(GetRowCount() - 1, 1);
463 Invalidate(GetRowRectPixel(nCurrentRow));
464 }
465 }
466
467 SaveModified();
468 }
469 return 0L;
470 }
471 //------------------------------------------------------------------
GetCellText(long _nRow,sal_uInt16 nColId) const472 String IndexFieldsControl::GetCellText(long _nRow,sal_uInt16 nColId) const
473 {
474 ConstIndexFieldsIterator aRow = m_aFields.end();
475 if ( _nRow >= 0 )
476 {
477 aRow = m_aFields.begin() + _nRow;
478 OSL_ENSURE(aRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
479 }
480 return GetRowCellText(aRow,nColId);
481 }
482 //------------------------------------------------------------------
GetRowCellText(const ConstIndexFieldsIterator & _rRow,sal_uInt16 nColId) const483 String IndexFieldsControl::GetRowCellText(const ConstIndexFieldsIterator& _rRow,sal_uInt16 nColId) const
484 {
485 if (_rRow < m_aFields.end())
486 {
487 switch (nColId)
488 {
489 case COLUMN_ID_FIELDNAME:
490 return _rRow->sFieldName;
491 case COLUMN_ID_ORDER:
492 if (0 == _rRow->sFieldName.Len())
493 return String();
494 else
495 return _rRow->bSortAscending ? m_sAscendingText : m_sDescendingText;
496 default:
497 OSL_ENSURE(sal_False, "IndexFieldsControl::GetCurrentRowCellText: invalid column id!");
498 }
499 }
500 return String();
501 }
502 //------------------------------------------------------------------
IsTabAllowed(sal_Bool) const503 sal_Bool IndexFieldsControl::IsTabAllowed(sal_Bool /*bForward*/) const
504 {
505 return sal_False;
506 }
507 //------------------------------------------------------------------
508
509 //......................................................................
510 } // namespace dbaui
511 //......................................................................
512
513