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_extensions.hxx" 30 #include "gridwizard.hxx" 31 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 32 #include <com/sun/star/sdbc/DataType.hpp> 33 #include <comphelper/stl_types.hxx> 34 #include <tools/string.hxx> 35 #include <com/sun/star/form/XGridColumnFactory.hpp> 36 #include <com/sun/star/awt/MouseWheelBehavior.hpp> 37 #include <com/sun/star/container/XNameContainer.hpp> 38 #include <tools/debug.hxx> 39 #include "dbptools.hxx" 40 #include "dbpilots.hrc" 41 42 #define GW_STATE_DATASOURCE_SELECTION 0 43 #define GW_STATE_FIELDSELECTION 1 44 45 //......................................................................... 46 namespace dbp 47 { 48 //......................................................................... 49 50 using namespace ::com::sun::star::uno; 51 using namespace ::com::sun::star::lang; 52 using namespace ::com::sun::star::beans; 53 using namespace ::com::sun::star::sdbc; 54 using namespace ::com::sun::star::container; 55 using namespace ::com::sun::star::form; 56 using namespace ::com::sun::star::awt; 57 using namespace ::svt; 58 59 //===================================================================== 60 //= OGridWizard 61 //===================================================================== 62 //--------------------------------------------------------------------- 63 OGridWizard::OGridWizard( Window* _pParent, 64 const Reference< XPropertySet >& _rxObjectModel, const Reference< XMultiServiceFactory >& _rxORB ) 65 :OControlWizard(_pParent, ModuleRes(RID_DLG_GRIDWIZARD), _rxObjectModel, _rxORB) 66 ,m_bHadDataSelection(sal_True) 67 { 68 initControlSettings(&m_aSettings); 69 70 m_pPrevPage->SetHelpId(HID_GRIDWIZARD_PREVIOUS); 71 m_pNextPage->SetHelpId(HID_GRIDWIZARD_NEXT); 72 m_pCancel->SetHelpId(HID_GRIDWIZARD_CANCEL); 73 m_pFinish->SetHelpId(HID_GRIDWIZARD_FINISH); 74 75 // if we do not need the data source selection page ... 76 if (!needDatasourceSelection()) 77 { // ... skip it! 78 skip(1); 79 m_bHadDataSelection = sal_False; 80 } 81 } 82 83 //--------------------------------------------------------------------- 84 sal_Bool OGridWizard::approveControl(sal_Int16 _nClassId) 85 { 86 if (FormComponentType::GRIDCONTROL != _nClassId) 87 return sal_False; 88 89 Reference< XGridColumnFactory > xColumnFactory(getContext().xObjectModel, UNO_QUERY); 90 if (!xColumnFactory.is()) 91 return sal_False; 92 93 return sal_True; 94 } 95 96 //--------------------------------------------------------------------- 97 void OGridWizard::implApplySettings() 98 { 99 const OControlWizardContext& rContext = getContext(); 100 101 // the factory for the columns 102 Reference< XGridColumnFactory > xColumnFactory(rContext.xObjectModel, UNO_QUERY); 103 DBG_ASSERT(xColumnFactory.is(), "OGridWizard::implApplySettings: should never have made it 'til here!"); 104 // (if we're here, what the hell happened in approveControl??) 105 106 // the container for the columns 107 Reference< XNameContainer > xColumnContainer(rContext.xObjectModel, UNO_QUERY); 108 DBG_ASSERT(xColumnContainer.is(), "OGridWizard::implApplySettings: no container!"); 109 110 if (!xColumnFactory.is() || !xColumnContainer.is()) 111 return; 112 113 static const ::rtl::OUString s_sDataFieldProperty = ::rtl::OUString::createFromAscii("DataField"); 114 static const ::rtl::OUString s_sLabelProperty = ::rtl::OUString::createFromAscii("Label"); 115 static const ::rtl::OUString s_sWidthProperty = ::rtl::OUString::createFromAscii("Width"); 116 static const ::rtl::OUString s_sMouseWheelBehavior = ::rtl::OUString::createFromAscii("MouseWheelBehavior"); 117 static const ::rtl::OUString s_sEmptyString; 118 119 // collect "descriptors" for the to-be-created (grid)columns 120 DECLARE_STL_VECTOR( ::rtl::OUString, StringArray ); 121 StringArray aColumnServiceNames; // service names to be used with the XGridColumnFactory 122 StringArray aColumnLabelPostfixes; // postfixes to append to the column labels 123 StringArray aFormFieldNames; // data field names 124 125 aColumnServiceNames.reserve(getSettings().aSelectedFields.getLength()); 126 aColumnLabelPostfixes.reserve(getSettings().aSelectedFields.getLength()); 127 aFormFieldNames.reserve(getSettings().aSelectedFields.getLength()); 128 129 // loop through the selected field names 130 const ::rtl::OUString* pSelectedFields = getSettings().aSelectedFields.getConstArray(); 131 const ::rtl::OUString* pEnd = pSelectedFields + getSettings().aSelectedFields.getLength(); 132 for (;pSelectedFields < pEnd; ++pSelectedFields) 133 { 134 // get the information for the selected column 135 sal_Int32 nFieldType = DataType::OTHER; 136 OControlWizardContext::TNameTypeMap::const_iterator aFind = rContext.aTypes.find(*pSelectedFields); 137 if ( aFind != rContext.aTypes.end() ) 138 nFieldType = aFind->second; 139 140 aFormFieldNames.push_back(*pSelectedFields); 141 switch (nFieldType) 142 { 143 case DataType::BIT: 144 case DataType::BOOLEAN: 145 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("CheckBox")); 146 aColumnLabelPostfixes.push_back(s_sEmptyString); 147 break; 148 149 case DataType::TINYINT: 150 case DataType::SMALLINT: 151 case DataType::INTEGER: 152 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("NumericField")); 153 aColumnLabelPostfixes.push_back(s_sEmptyString); 154 break; 155 156 case DataType::FLOAT: 157 case DataType::REAL: 158 case DataType::DOUBLE: 159 case DataType::NUMERIC: 160 case DataType::DECIMAL: 161 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("FormattedField")); 162 aColumnLabelPostfixes.push_back(s_sEmptyString); 163 break; 164 165 case DataType::DATE: 166 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("DateField")); 167 aColumnLabelPostfixes.push_back(s_sEmptyString); 168 break; 169 170 case DataType::TIME: 171 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("TimeField")); 172 aColumnLabelPostfixes.push_back(s_sEmptyString); 173 break; 174 175 case DataType::TIMESTAMP: 176 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("DateField")); 177 aColumnLabelPostfixes.push_back(String(ModuleRes(RID_STR_DATEPOSTFIX))); 178 179 aFormFieldNames.push_back(*pSelectedFields); 180 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("TimeField")); 181 aColumnLabelPostfixes.push_back(String(ModuleRes(RID_STR_TIMEPOSTFIX))); 182 break; 183 184 default: 185 aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("TextField")); 186 aColumnLabelPostfixes.push_back(s_sEmptyString); 187 } 188 } 189 190 DBG_ASSERT( aFormFieldNames.size() == aColumnServiceNames.size() 191 && aColumnServiceNames.size() == aColumnLabelPostfixes.size(), 192 "OGridWizard::implApplySettings: inconsistent descriptor sequences!"); 193 194 // now loop through the descriptions and create the (grid)columns out of th descriptors 195 { 196 Reference< XNameAccess > xExistenceChecker(xColumnContainer.get()); 197 198 ConstStringArrayIterator pColumnServiceName = aColumnServiceNames.begin(); 199 ConstStringArrayIterator pColumnLabelPostfix = aColumnLabelPostfixes.begin(); 200 ConstStringArrayIterator pFormFieldName = aFormFieldNames.begin(); 201 ConstStringArrayIterator pColumnServiceNameEnd = aColumnServiceNames.end(); 202 203 for (;pColumnServiceName < pColumnServiceNameEnd; ++pColumnServiceName, ++pColumnLabelPostfix, ++pFormFieldName) 204 { 205 // create a (grid)column for the (resultset)column 206 try 207 { 208 Reference< XPropertySet > xColumn( xColumnFactory->createColumn(*pColumnServiceName), UNO_SET_THROW ); 209 Reference< XPropertySetInfo > xColumnPSI( xColumn->getPropertySetInfo(), UNO_SET_THROW ); 210 211 ::rtl::OUString sColumnName(*pColumnServiceName); 212 disambiguateName(xExistenceChecker, sColumnName); 213 214 // the data field the column should be bound to 215 xColumn->setPropertyValue(s_sDataFieldProperty, makeAny(*pFormFieldName)); 216 // the label 217 xColumn->setPropertyValue(s_sLabelProperty, makeAny(::rtl::OUString(*pFormFieldName) += *pColumnLabelPostfix)); 218 // the width (<void/> => column will be auto-sized) 219 xColumn->setPropertyValue(s_sWidthProperty, Any()); 220 221 if ( xColumnPSI->hasPropertyByName( s_sMouseWheelBehavior ) ) 222 xColumn->setPropertyValue( s_sMouseWheelBehavior, makeAny( MouseWheelBehavior::SCROLL_DISABLED ) ); 223 224 // insert the column 225 xColumnContainer->insertByName(sColumnName, makeAny(xColumn)); 226 } 227 catch(Exception&) 228 { 229 DBG_ERROR( ::rtl::OString("OGridWizard::implApplySettings: unexpected exception while creating the grid column for field ") 230 += ::rtl::OString(pFormFieldName->getStr(), pFormFieldName->getLength(), gsl_getSystemTextEncoding()) 231 += ::rtl::OString("!")); 232 } 233 } 234 } 235 } 236 237 //--------------------------------------------------------------------- 238 OWizardPage* OGridWizard::createPage(WizardState _nState) 239 { 240 switch (_nState) 241 { 242 case GW_STATE_DATASOURCE_SELECTION: 243 return new OTableSelectionPage(this); 244 case GW_STATE_FIELDSELECTION: 245 return new OGridFieldsSelection(this); 246 } 247 248 return NULL; 249 } 250 251 //--------------------------------------------------------------------- 252 WizardTypes::WizardState OGridWizard::determineNextState( WizardState _nCurrentState ) const 253 { 254 switch (_nCurrentState) 255 { 256 case GW_STATE_DATASOURCE_SELECTION: 257 return GW_STATE_FIELDSELECTION; 258 case GW_STATE_FIELDSELECTION: 259 return WZS_INVALID_STATE; 260 } 261 262 return WZS_INVALID_STATE; 263 } 264 265 //--------------------------------------------------------------------- 266 void OGridWizard::enterState(WizardState _nState) 267 { 268 OControlWizard::enterState(_nState); 269 270 enableButtons(WZB_PREVIOUS, m_bHadDataSelection ? (GW_STATE_DATASOURCE_SELECTION < _nState) : GW_STATE_FIELDSELECTION < _nState); 271 enableButtons(WZB_NEXT, GW_STATE_FIELDSELECTION != _nState); 272 if (_nState < GW_STATE_FIELDSELECTION) 273 enableButtons(WZB_FINISH, sal_False); 274 275 if (GW_STATE_FIELDSELECTION == _nState) 276 defaultButton(WZB_FINISH); 277 } 278 279 //--------------------------------------------------------------------- 280 sal_Bool OGridWizard::leaveState(WizardState _nState) 281 { 282 if (!OControlWizard::leaveState(_nState)) 283 return sal_False; 284 285 if (GW_STATE_FIELDSELECTION == _nState) 286 defaultButton(WZB_NEXT); 287 288 return sal_True; 289 } 290 291 //--------------------------------------------------------------------- 292 sal_Bool OGridWizard::onFinish() 293 { 294 if ( !OControlWizard::onFinish() ) 295 return sal_False; 296 297 implApplySettings(); 298 299 return sal_True; 300 } 301 302 //===================================================================== 303 //= OGridFieldsSelection 304 //===================================================================== 305 //--------------------------------------------------------------------- 306 OGridFieldsSelection::OGridFieldsSelection( OGridWizard* _pParent ) 307 :OGridPage(_pParent, ModuleRes(RID_PAGE_GW_FIELDSELECTION)) 308 ,m_aFrame (this, ModuleRes(FL_FRAME)) 309 ,m_aExistFieldsLabel (this, ModuleRes(FT_EXISTING_FIELDS)) 310 ,m_aExistFields (this, ModuleRes(LB_EXISTING_FIELDS)) 311 ,m_aSelectOne (this, ModuleRes(PB_FIELDRIGHT)) 312 ,m_aSelectAll (this, ModuleRes(PB_ALLFIELDSRIGHT)) 313 ,m_aDeselectOne (this, ModuleRes(PB_FIELDLEFT)) 314 ,m_aDeselectAll (this, ModuleRes(PB_ALLFIELDSLEFT)) 315 ,m_aSelFieldsLabel (this, ModuleRes(FT_SELECTED_FIELDS)) 316 ,m_aSelFields (this, ModuleRes(LB_SELECTED_FIELDS)) 317 { 318 FreeResource(); 319 320 enableFormDatasourceDisplay(); 321 322 m_aSelectOne.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveOneEntry)); 323 m_aSelectAll.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveAllEntries)); 324 m_aDeselectOne.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveOneEntry)); 325 m_aDeselectAll.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveAllEntries)); 326 327 m_aExistFields.SetSelectHdl(LINK(this, OGridFieldsSelection, OnEntrySelected)); 328 m_aSelFields.SetSelectHdl(LINK(this, OGridFieldsSelection, OnEntrySelected)); 329 m_aExistFields.SetDoubleClickHdl(LINK(this, OGridFieldsSelection, OnEntryDoubleClicked)); 330 m_aSelFields.SetDoubleClickHdl(LINK(this, OGridFieldsSelection, OnEntryDoubleClicked)); 331 } 332 333 //--------------------------------------------------------------------- 334 void OGridFieldsSelection::ActivatePage() 335 { 336 OGridPage::ActivatePage(); 337 m_aExistFields.GrabFocus(); 338 } 339 340 //--------------------------------------------------------------------- 341 bool OGridFieldsSelection::canAdvance() const 342 { 343 return false; 344 // we're the last page in our wizard 345 } 346 347 //--------------------------------------------------------------------- 348 void OGridFieldsSelection::initializePage() 349 { 350 OGridPage::initializePage(); 351 352 const OControlWizardContext& rContext = getContext(); 353 fillListBox(m_aExistFields, rContext.aFieldNames); 354 355 m_aSelFields.Clear(); 356 const OGridSettings& rSettings = getSettings(); 357 const ::rtl::OUString* pSelected = rSettings.aSelectedFields.getConstArray(); 358 const ::rtl::OUString* pEnd = pSelected + rSettings.aSelectedFields.getLength(); 359 for (; pSelected < pEnd; ++pSelected) 360 { 361 m_aSelFields.InsertEntry(*pSelected); 362 m_aExistFields.RemoveEntry(*pSelected); 363 } 364 365 implCheckButtons(); 366 } 367 368 //--------------------------------------------------------------------- 369 sal_Bool OGridFieldsSelection::commitPage( ::svt::WizardTypes::CommitPageReason _eReason ) 370 { 371 if (!OGridPage::commitPage(_eReason)) 372 return sal_False; 373 374 OGridSettings& rSettings = getSettings(); 375 sal_uInt16 nSelected = m_aSelFields.GetEntryCount(); 376 377 rSettings.aSelectedFields.realloc(nSelected); 378 ::rtl::OUString* pSelected = rSettings.aSelectedFields.getArray(); 379 380 for (sal_uInt16 i=0; i<nSelected; ++i, ++pSelected) 381 *pSelected = m_aSelFields.GetEntry(i); 382 383 return sal_True; 384 } 385 386 //--------------------------------------------------------------------- 387 void OGridFieldsSelection::implCheckButtons() 388 { 389 m_aSelectOne.Enable(m_aExistFields.GetSelectEntryCount() != 0); 390 m_aSelectAll.Enable(m_aExistFields.GetEntryCount() != 0); 391 392 m_aDeselectOne.Enable(m_aSelFields.GetSelectEntryCount() != 0); 393 m_aDeselectAll.Enable(m_aSelFields.GetEntryCount() != 0); 394 395 getDialog()->enableButtons(WZB_FINISH, 0 != m_aSelFields.GetEntryCount()); 396 } 397 398 //--------------------------------------------------------------------- 399 IMPL_LINK(OGridFieldsSelection, OnEntryDoubleClicked, ListBox*, _pList) 400 { 401 PushButton* pSimulateButton = &m_aExistFields == _pList ? &m_aSelectOne : &m_aDeselectOne; 402 if (pSimulateButton->IsEnabled()) 403 return OnMoveOneEntry( pSimulateButton ); 404 else 405 return 1L; 406 } 407 408 //--------------------------------------------------------------------- 409 IMPL_LINK(OGridFieldsSelection, OnEntrySelected, ListBox*, /*NOTINTERESTEDIN*/) 410 { 411 implCheckButtons(); 412 return 0L; 413 } 414 415 //--------------------------------------------------------------------- 416 IMPL_LINK(OGridFieldsSelection, OnMoveOneEntry, PushButton*, _pButton) 417 { 418 sal_Bool bMoveRight = (&m_aSelectOne == _pButton); 419 ListBox& rMoveTo = bMoveRight ? m_aSelFields : m_aExistFields; 420 421 // the index of the selected entry 422 sal_uInt16 nSelected = bMoveRight ? m_aExistFields.GetSelectEntryPos() : m_aSelFields.GetSelectEntryPos(); 423 // the (original) relative position of the entry 424 sal_IntPtr nRelativeIndex = reinterpret_cast<sal_IntPtr>(bMoveRight ? m_aExistFields.GetEntryData(nSelected) : m_aSelFields.GetEntryData(nSelected)); 425 426 sal_uInt16 nInsertPos = LISTBOX_APPEND; 427 if (!bMoveRight) 428 { // need to determine an insert pos which reflects the original 429 nInsertPos = 0; 430 while (nInsertPos < rMoveTo.GetEntryCount()) 431 { 432 if (reinterpret_cast<sal_IntPtr>(rMoveTo.GetEntryData(nInsertPos)) > nRelativeIndex) 433 break; 434 ++nInsertPos; 435 } 436 } 437 438 // the text of the entry to move 439 String sMovingEntry = bMoveRight ? m_aExistFields.GetEntry(nSelected) : m_aSelFields.GetEntry(nSelected); 440 441 // insert the entry 442 nInsertPos = rMoveTo.InsertEntry(sMovingEntry, nInsertPos); 443 // preserve it's "relative position" entry data 444 rMoveTo.SetEntryData(nInsertPos, reinterpret_cast<void*>(nRelativeIndex)); 445 446 // remove the entry from it's old list 447 if (bMoveRight) 448 { 449 sal_uInt16 nSelectPos = m_aExistFields.GetSelectEntryPos(); 450 m_aExistFields.RemoveEntry(nSelected); 451 if ((LISTBOX_ENTRY_NOTFOUND != nSelectPos) && (nSelectPos < m_aExistFields.GetEntryCount())) 452 m_aExistFields.SelectEntryPos(nSelectPos); 453 454 m_aExistFields.GrabFocus(); 455 } 456 else 457 { 458 sal_uInt16 nSelectPos = m_aSelFields.GetSelectEntryPos(); 459 m_aSelFields.RemoveEntry(nSelected); 460 if ((LISTBOX_ENTRY_NOTFOUND != nSelectPos) && (nSelectPos < m_aSelFields.GetEntryCount())) 461 m_aSelFields.SelectEntryPos(nSelectPos); 462 463 m_aSelFields.GrabFocus(); 464 } 465 466 implCheckButtons(); 467 return 0; 468 } 469 470 //--------------------------------------------------------------------- 471 IMPL_LINK(OGridFieldsSelection, OnMoveAllEntries, PushButton*, _pButton) 472 { 473 sal_Bool bMoveRight = (&m_aSelectAll == _pButton); 474 m_aExistFields.Clear(); 475 m_aSelFields.Clear(); 476 fillListBox(bMoveRight ? m_aSelFields : m_aExistFields, getContext().aFieldNames); 477 478 implCheckButtons(); 479 return 0; 480 } 481 482 //......................................................................... 483 } // namespace dbp 484 //......................................................................... 485 486