xref: /AOO41X/main/dbaccess/source/ui/dlg/indexfieldscontrol.cxx (revision 96de54900b79e13b861fbc62cbf36018b54e21b7)
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_dbaccess.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 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