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