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