1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <reffact.hxx> 21 #include <document.hxx> 22 #include <globstr.hrc> 23 #include <scresid.hxx> 24 #include <docsh.hxx> 25 #include <crnrdlg.hxx> 26 #include <vcl/svapp.hxx> 27 #include <vcl/weld.hxx> 28 #include <memory> 29 30 namespace 31 { 32 void ERRORBOX(weld::Window* pParent, const OUString& rString) 33 { 34 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, 35 VclMessageType::Warning, VclButtonsType::Ok, 36 rString)); 37 xBox->run(); 38 } 39 40 int QUERYBOX(weld::Window* pParent, const OUString& rString) 41 { 42 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, 43 VclMessageType::Question, VclButtonsType::YesNo, 44 rString)); 45 xBox->set_default_response(RET_YES); 46 return xBox->run(); 47 } 48 49 } 50 51 const sal_uLong nEntryDataCol = 0; 52 const sal_uLong nEntryDataRow = 1; 53 const sal_uLong nEntryDataDelim = 2; 54 55 56 // note: some of the initialisation is done in Init 57 ScColRowNameRangesDlg::ScColRowNameRangesDlg( SfxBindings* pB, 58 SfxChildWindow* pCW, 59 weld::Window* pParent, 60 ScViewData* ptrViewData ) 61 62 : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/namerangesdialog.ui", "NameRangesDialog") 63 , pViewData(ptrViewData) 64 , pDoc(ptrViewData->GetDocument()) 65 , bDlgLostFocus(false) 66 , m_pEdActive(nullptr) 67 , m_xLbRange(m_xBuilder->weld_tree_view("range")) 68 , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry("edassign"))) 69 , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button("rbassign"))) 70 , m_xBtnColHead(m_xBuilder->weld_radio_button("colhead")) 71 , m_xBtnRowHead(m_xBuilder->weld_radio_button("rowhead")) 72 , m_xEdAssign2(new formula::RefEdit(m_xBuilder->weld_entry("edassign2"))) 73 , m_xRbAssign2(new formula::RefButton(m_xBuilder->weld_button("rbassign2"))) 74 , m_xBtnOk(m_xBuilder->weld_button("ok")) 75 , m_xBtnCancel(m_xBuilder->weld_button("cancel")) 76 , m_xBtnAdd(m_xBuilder->weld_button("add")) 77 , m_xBtnRemove(m_xBuilder->weld_button("delete")) 78 , m_xRangeFrame(m_xBuilder->weld_frame("rangeframe")) 79 , m_xRangeFT(m_xRangeFrame->weld_label_widget()) 80 , m_xDataFT(m_xBuilder->weld_label("datarange")) 81 { 82 m_xRbAssign->SetReferences(this, m_xEdAssign.get()); 83 m_xEdAssign->SetReferences(this, m_xRangeFT.get()); 84 m_xRbAssign2->SetReferences(this, m_xEdAssign2.get()); 85 m_xEdAssign2->SetReferences(this, m_xDataFT.get()); 86 87 xColNameRanges = pDoc->GetColNameRanges()->Clone(); 88 xRowNameRanges = pDoc->GetRowNameRanges()->Clone(); 89 Init(); 90 } 91 92 ScColRowNameRangesDlg::~ScColRowNameRangesDlg() 93 { 94 } 95 96 // initialises event handlers and start parameters in the dialog 97 void ScColRowNameRangesDlg::Init() 98 { 99 m_xBtnOk->connect_clicked ( LINK( this, ScColRowNameRangesDlg, OkBtnHdl ) ); 100 m_xBtnCancel->connect_clicked ( LINK( this, ScColRowNameRangesDlg, CancelBtnHdl ) ); 101 m_xBtnAdd->connect_clicked ( LINK( this, ScColRowNameRangesDlg, AddBtnHdl ) ); 102 m_xBtnRemove->connect_clicked ( LINK( this, ScColRowNameRangesDlg, RemoveBtnHdl ) ); 103 m_xLbRange->connect_changed( LINK( this, ScColRowNameRangesDlg, Range1SelectHdl ) ); 104 m_xEdAssign->SetModifyHdl ( LINK( this, ScColRowNameRangesDlg, Range1DataModifyHdl ) ); 105 m_xBtnColHead->connect_clicked ( LINK( this, ScColRowNameRangesDlg, ColClickHdl ) ); 106 m_xBtnRowHead->connect_clicked ( LINK( this, ScColRowNameRangesDlg, RowClickHdl ) ); 107 m_xEdAssign2->SetModifyHdl ( LINK( this, ScColRowNameRangesDlg, Range2DataModifyHdl ) ); 108 109 Link<formula::RefEdit&,void> aEditLink = LINK( this, ScColRowNameRangesDlg, GetEditFocusHdl ); 110 m_xEdAssign->SetGetFocusHdl( aEditLink ); 111 m_xEdAssign2->SetGetFocusHdl( aEditLink ); 112 113 Link<formula::RefButton&,void> aButtonLink = LINK( this, ScColRowNameRangesDlg, GetButtonFocusHdl ); 114 m_xRbAssign->SetGetFocusHdl( aButtonLink ); 115 m_xRbAssign2->SetGetFocusHdl( aButtonLink ); 116 117 aEditLink = LINK( this, ScColRowNameRangesDlg, LoseEditFocusHdl ); 118 m_xEdAssign->SetLoseFocusHdl( aEditLink ); 119 m_xEdAssign2->SetLoseFocusHdl( aEditLink ); 120 121 aButtonLink = LINK( this, ScColRowNameRangesDlg, LoseButtonFocusHdl ); 122 m_xRbAssign2->SetLoseFocusHdl( aButtonLink ); 123 m_xRbAssign->SetLoseFocusHdl( aButtonLink ); 124 125 m_pEdActive = m_xEdAssign.get(); 126 127 UpdateNames(); 128 129 if (pViewData) 130 { 131 SCCOL nStartCol = 0; 132 SCROW nStartRow = 0; 133 SCTAB nStartTab = 0; 134 SCCOL nEndCol = 0; 135 SCROW nEndRow = 0; 136 SCTAB nEndTab = 0; 137 pViewData->GetSimpleArea( nStartCol, nStartRow, nStartTab, 138 nEndCol, nEndRow, nEndTab ); 139 SetColRowData( ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab)); 140 } 141 else 142 { 143 m_xBtnColHead->set_active(true); 144 m_xBtnRowHead->set_active(false); 145 m_xEdAssign->SetText( EMPTY_OUSTRING ); 146 m_xEdAssign2->SetText( EMPTY_OUSTRING ); 147 } 148 149 m_xBtnColHead->set_sensitive(true); 150 m_xBtnRowHead->set_sensitive(true); 151 m_xEdAssign->GetWidget()->set_sensitive(true); 152 m_xEdAssign->GrabFocus(); 153 m_xRbAssign->GetWidget()->set_sensitive(true); 154 155 Range1SelectHdl( *m_xLbRange ); 156 } 157 158 // set data range of a labeled range to default values and set the 159 // form elements for the reference 160 void ScColRowNameRangesDlg::SetColRowData( const ScRange& rLabelRange, bool bRef) 161 { 162 theCurData = theCurArea = rLabelRange; 163 bool bValid = true; 164 SCCOL nCol1 = theCurArea.aStart.Col(); 165 SCCOL nCol2 = theCurArea.aEnd.Col(); 166 SCROW nRow1 = theCurArea.aStart.Row(); 167 SCROW nRow2 = theCurArea.aEnd.Row(); 168 if ( (static_cast<SCCOLROW>(nCol2 - nCol1) >= nRow2 - nRow1) || (nCol1 == 0 && nCol2 == pDoc->MaxCol()) ) 169 { // Column headers and the limiting case of the whole sheet 170 m_xBtnColHead->set_active(true); 171 m_xBtnRowHead->set_active(false); 172 if ( nRow2 == pDoc->MaxRow() ) 173 { 174 if ( nRow1 == 0 ) 175 bValid = false; // limiting case of the whole sheet 176 else 177 { // Header at bottom, data above 178 theCurData.aStart.SetRow( 0 ); 179 theCurData.aEnd.SetRow( nRow1 - 1 ); 180 } 181 } 182 else 183 { // Header at top, data below 184 theCurData.aStart.SetRow( nRow2 + 1 ); 185 theCurData.aEnd.SetRow( pDoc->MaxRow() ); 186 } 187 } 188 else 189 { // Column headers 190 m_xBtnRowHead->set_active(true); 191 m_xBtnColHead->set_active(false); 192 if ( nCol2 == pDoc->MaxCol() ) 193 { // Header at the right, data to the left 194 theCurData.aStart.SetCol( 0 ); 195 theCurData.aEnd.SetCol( nCol2 - 1 ); 196 } 197 else 198 { // Header at the left, data to the right 199 theCurData.aStart.SetCol( nCol2 + 1 ); 200 theCurData.aEnd.SetCol( pDoc->MaxCol() ); 201 } 202 } 203 if ( bValid ) 204 { 205 const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); 206 OUString aStr(theCurArea.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, eConv)); 207 208 if(bRef) 209 m_xEdAssign->SetRefString( aStr ); 210 else 211 m_xEdAssign->SetText( aStr ); 212 213 m_xEdAssign->SetCursorAtLast(); 214 aStr = theCurData.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, eConv); 215 216 if(bRef) 217 m_xEdAssign2->SetRefString( aStr ); 218 else 219 m_xEdAssign2->SetText( aStr ); 220 } 221 else 222 { 223 theCurData = theCurArea = ScRange(); 224 225 if(bRef) 226 { 227 m_xEdAssign->SetRefString( EMPTY_OUSTRING ); 228 m_xEdAssign2->SetRefString( EMPTY_OUSTRING ); 229 } 230 else 231 { 232 m_xEdAssign->SetText( EMPTY_OUSTRING ); 233 m_xEdAssign2->SetText( EMPTY_OUSTRING ); 234 } 235 236 m_xBtnColHead->set_sensitive(false); 237 m_xBtnRowHead->set_sensitive(false); 238 m_xEdAssign2->GetWidget()->set_sensitive(false); 239 m_xRbAssign2->GetWidget()->set_sensitive(false); 240 } 241 } 242 243 // adjust label range and set the data reference form element 244 void ScColRowNameRangesDlg::AdjustColRowData( const ScRange& rDataRange, bool bRef) 245 { 246 theCurData = rDataRange; 247 if ( m_xBtnColHead->get_active() ) 248 { // Data range is the same columns as the header 249 theCurData.aStart.SetCol( theCurArea.aStart.Col() ); 250 theCurData.aEnd.SetCol( theCurArea.aEnd.Col() ); 251 if ( theCurData.Intersects( theCurArea ) ) 252 { 253 SCROW nRow1 = theCurArea.aStart.Row(); 254 SCROW nRow2 = theCurArea.aEnd.Row(); 255 if ( nRow1 > 0 256 && (theCurData.aEnd.Row() < nRow2 || nRow2 == pDoc->MaxRow()) ) 257 { // Data above header 258 theCurData.aEnd.SetRow( nRow1 - 1 ); 259 if ( theCurData.aStart.Row() > theCurData.aEnd.Row() ) 260 theCurData.aStart.SetRow( theCurData.aEnd.Row() ); 261 } 262 else 263 { // Data below header 264 theCurData.aStart.SetRow( nRow2 + 1 ); 265 if ( theCurData.aStart.Row() > theCurData.aEnd.Row() ) 266 theCurData.aEnd.SetRow( theCurData.aStart.Row() ); 267 } 268 } 269 } 270 else 271 { // Data range in the same rows as header 272 theCurData.aStart.SetRow( theCurArea.aStart.Row() ); 273 theCurData.aEnd.SetRow( theCurArea.aEnd.Row() ); 274 if ( theCurData.Intersects( theCurArea ) ) 275 { 276 SCCOL nCol1 = theCurArea.aStart.Col(); 277 SCCOL nCol2 = theCurArea.aEnd.Col(); 278 if ( nCol1 > 0 279 && (theCurData.aEnd.Col() < nCol2 || nCol2 == pDoc->MaxCol()) ) 280 { // Data left of header 281 theCurData.aEnd.SetCol( nCol1 - 1 ); 282 if ( theCurData.aStart.Col() > theCurData.aEnd.Col() ) 283 theCurData.aStart.SetCol( theCurData.aEnd.Col() ); 284 } 285 else 286 { // Data right of header 287 theCurData.aStart.SetCol( nCol2 + 1 ); 288 if ( theCurData.aStart.Col() > theCurData.aEnd.Col() ) 289 theCurData.aEnd.SetCol( theCurData.aStart.Col() ); 290 } 291 } 292 } 293 OUString aStr(theCurData.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, pDoc->GetAddressConvention())); 294 295 if(bRef) 296 m_xEdAssign2->SetRefString( aStr ); 297 else 298 m_xEdAssign2->SetText( aStr ); 299 300 m_xEdAssign2->SetCursorAtLast(); 301 } 302 303 // Set the reference to a cell range selected with the mouse and update 304 // the selection form element 305 void ScColRowNameRangesDlg::SetReference( const ScRange& rRef, ScDocument& /* rDoc */ ) 306 { 307 if ( m_pEdActive ) 308 { 309 if ( rRef.aStart != rRef.aEnd ) 310 RefInputStart( m_pEdActive ); 311 312 if (m_pEdActive == m_xEdAssign.get()) 313 SetColRowData( rRef, true ); 314 else 315 AdjustColRowData( rRef, true ); 316 m_xBtnColHead->set_sensitive(true); 317 m_xBtnRowHead->set_sensitive(true); 318 m_xBtnAdd->set_sensitive(true); 319 m_xBtnRemove->set_sensitive(false); 320 } 321 } 322 323 void ScColRowNameRangesDlg::Close() 324 { 325 DoClose( ScColRowNameRangesDlgWrapper::GetChildWindowId() ); 326 } 327 328 void ScColRowNameRangesDlg::SetActive() 329 { 330 if ( bDlgLostFocus ) 331 { 332 bDlgLostFocus = false; 333 if( m_pEdActive ) 334 m_pEdActive->GrabFocus(); 335 } 336 else 337 m_xDialog->grab_focus(); 338 339 if( m_pEdActive == m_xEdAssign.get() ) 340 Range1DataModifyHdl( *m_xEdAssign ); 341 else if( m_pEdActive == m_xEdAssign2.get() ) 342 Range2DataModifyHdl( *m_xEdAssign2 ); 343 344 RefInputDone(); 345 } 346 347 void ScColRowNameRangesDlg::UpdateNames() 348 { 349 m_xLbRange->freeze(); 350 351 m_xLbRange->clear(); 352 aRangeMap.clear(); 353 m_xEdAssign->SetText( EMPTY_OUSTRING ); 354 355 size_t nCount, j; 356 357 SCCOL nCol1; 358 SCROW nRow1; //Extension for range names 359 SCTAB nTab1; 360 SCCOL nCol2; 361 SCROW nRow2; 362 SCTAB nTab2; 363 OUString rString; 364 const ScAddress::Details aDetails(pDoc->GetAddressConvention()); 365 366 OUString strDelim(" --- "); 367 OUString aString = strDelim + ScResId( STR_COLUMN ) + strDelim; 368 m_xLbRange->append(OUString::number(nEntryDataDelim), aString); 369 if ( xColNameRanges->size() > 0 ) 370 { 371 std::vector<const ScRangePair*> aSortArray(xColNameRanges->CreateNameSortedArray( 372 pDoc )); 373 nCount = aSortArray.size(); 374 for ( j=0; j < nCount; j++ ) 375 { 376 const ScRange aRange(aSortArray[j]->GetRange(0)); 377 aString = aRange.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, aDetails); 378 379 //@008 get range parameters from document 380 aSortArray[j]->GetRange(0).GetVars( nCol1, nRow1, nTab1, 381 nCol2, nRow2, nTab2 ); 382 SCCOL q=nCol1+3; 383 if(q>nCol2) q=nCol2; 384 //@008 construct string 385 OUStringBuffer strShow = " ["; 386 rString = pDoc->GetString(nCol1, nRow1, nTab1); 387 strShow.append(rString); 388 for(SCCOL i=nCol1+1;i<=q;i++) 389 { 390 strShow.append(", "); 391 rString = pDoc->GetString(i, nRow1, nTab1); 392 strShow.append(rString); 393 } 394 if(q<nCol2) // Too long? Add ",..." 395 { 396 strShow.append(", ..."); 397 } 398 strShow.append("]"); 399 400 //@008 Add string to listbox 401 OUString aInsStr = aString + strShow.makeStringAndClear(); 402 aRangeMap.emplace( aInsStr, aRange ); 403 m_xLbRange->append(OUString::number(nEntryDataDelim), aInsStr); 404 } 405 } 406 aString = strDelim + ScResId( STR_ROW ) + strDelim; 407 m_xLbRange->append(OUString::number(nEntryDataDelim), aString); 408 if ( xRowNameRanges->size() > 0 ) 409 { 410 std::vector<const ScRangePair*> aSortArray(xRowNameRanges->CreateNameSortedArray( 411 pDoc )); 412 nCount = aSortArray.size(); 413 for ( j=0; j < nCount; j++ ) 414 { 415 const ScRange aRange(aSortArray[j]->GetRange(0)); 416 aString = aRange.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, aDetails); 417 418 //@008 Build string for rows below 419 aSortArray[j]->GetRange(0).GetVars( nCol1, nRow1, nTab1, 420 nCol2, nRow2, nTab2 ); 421 SCROW q=nRow1+3; 422 if(q>nRow2) q=nRow2; 423 OUStringBuffer strShow = " ["; 424 rString = pDoc->GetString(nCol1, nRow1, nTab1); 425 strShow.append(rString); 426 for(SCROW i=nRow1+1;i<=q;i++) 427 { 428 strShow.append(", "); 429 rString = pDoc->GetString(nCol1, i, nTab1); 430 strShow.append(rString); 431 } 432 if(q<nRow2) 433 { 434 strShow.append(", ..."); 435 } 436 strShow.append("]"); 437 438 OUString aInsStr = aString + strShow.makeStringAndClear(); 439 aRangeMap.emplace( aInsStr, aRange ); 440 m_xLbRange->append(OUString::number(nEntryDataRow), aInsStr); 441 } 442 } 443 444 m_xLbRange->thaw(); 445 } 446 447 void ScColRowNameRangesDlg::UpdateRangeData( const ScRange& rRange, bool bColName ) 448 { 449 ScRangePair* pPair = nullptr; 450 bool bFound = false; 451 if ( bColName && (pPair = xColNameRanges->Find( rRange )) != nullptr ) 452 bFound = true; 453 else if ( !bColName && (pPair = xRowNameRanges->Find( rRange )) != nullptr ) 454 bFound = true; 455 456 if ( bFound ) 457 { 458 const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); 459 theCurArea = rRange; 460 OUString aStr(theCurArea.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, eConv)); 461 m_xEdAssign->SetText( aStr ); 462 m_xBtnAdd->set_sensitive(false); 463 m_xBtnRemove->set_sensitive(true); 464 m_xBtnColHead->set_active(bColName); 465 m_xBtnRowHead->set_active(!bColName); 466 theCurData = pPair->GetRange(1); 467 aStr = theCurData.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, eConv); 468 m_xEdAssign2->SetText( aStr ); 469 } 470 else 471 { 472 m_xBtnAdd->set_sensitive(true); 473 m_xBtnRemove->set_sensitive(false); 474 } 475 m_xBtnColHead->set_sensitive(true); 476 m_xBtnRowHead->set_sensitive(true); 477 m_xEdAssign2->GetWidget()->set_sensitive(true); 478 m_xRbAssign2->GetWidget()->set_sensitive(true); 479 } 480 481 bool ScColRowNameRangesDlg::IsRefInputMode() const 482 { 483 return (m_pEdActive != nullptr); 484 } 485 486 // Handler: 487 488 // handler called when OK is clicked, calls the add button handler before 489 // passing the range lists to the document 490 IMPL_LINK_NOARG(ScColRowNameRangesDlg, OkBtnHdl, weld::Button&, void) 491 { 492 AddBtnHdl(*m_xBtnAdd); 493 494 // assign RangeLists to the references in the document 495 pDoc->GetColNameRangesRef() = xColNameRanges; 496 pDoc->GetRowNameRangesRef() = xRowNameRanges; 497 // changed ranges need to take effect 498 pDoc->CompileColRowNameFormula(); 499 ScDocShell* pDocShell = pViewData->GetDocShell(); 500 pDocShell->PostPaint(ScRange(0, 0, 0, pDoc->MaxCol(), pDoc->MaxRow(), MAXTAB), PaintPartFlags::Grid); 501 pDocShell->SetDocumentModified(); 502 503 response(RET_OK); 504 } 505 506 IMPL_LINK_NOARG(ScColRowNameRangesDlg, CancelBtnHdl, weld::Button&, void) 507 { 508 response(RET_CANCEL); 509 } 510 511 // handler called when add button clicked: set ranges and add to listbox 512 IMPL_LINK_NOARG(ScColRowNameRangesDlg, AddBtnHdl, weld::Button&, void) 513 { 514 OUString aNewArea( m_xEdAssign->GetText() ); 515 OUString aNewData( m_xEdAssign2->GetText() ); 516 517 if ( !aNewArea.isEmpty() && !aNewData.isEmpty() ) 518 { 519 const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); 520 ScRange aRange1, aRange2; 521 bool bOk1 = (aRange1.ParseAny( aNewArea, pDoc, eConv ) & ScRefFlags::VALID) == ScRefFlags::VALID; 522 if ( bOk1 && (aRange2.ParseAny( aNewData, pDoc, eConv ) & ScRefFlags::VALID) == ScRefFlags::VALID) 523 { 524 theCurArea = aRange1; 525 AdjustColRowData( aRange2 ); 526 ScRangePair* pPair; 527 if ( ( pPair = xColNameRanges->Find( theCurArea ) ) != nullptr ) 528 { 529 xColNameRanges->Remove( *pPair ); 530 } 531 if ( ( pPair = xRowNameRanges->Find( theCurArea ) ) != nullptr ) 532 { 533 xRowNameRanges->Remove( *pPair ); 534 } 535 if ( m_xBtnColHead->get_active() ) 536 xColNameRanges->Join( ScRangePair( theCurArea, theCurData ) ); 537 else 538 xRowNameRanges->Join( ScRangePair( theCurArea, theCurData ) ); 539 540 UpdateNames(); 541 542 m_xEdAssign->GrabFocus(); 543 m_xBtnAdd->set_sensitive(false); 544 m_xBtnRemove->set_sensitive(false); 545 m_xEdAssign->SetText( EMPTY_OUSTRING ); 546 m_xBtnColHead->set_active(true); 547 m_xBtnRowHead->set_active(false); 548 m_xEdAssign2->SetText( EMPTY_OUSTRING ); 549 theCurArea = ScRange(); 550 theCurData = theCurArea; 551 Range1SelectHdl( *m_xLbRange ); 552 } 553 else 554 { 555 ERRORBOX(m_xDialog.get(), ScResId(STR_INVALIDTABNAME)); 556 if ( !bOk1 ) 557 m_xEdAssign->GrabFocus(); 558 else 559 m_xEdAssign2->GrabFocus(); 560 } 561 } 562 } 563 564 IMPL_LINK_NOARG(ScColRowNameRangesDlg, RemoveBtnHdl, weld::Button&, void) 565 { 566 OUString aRangeStr = m_xLbRange->get_selected_text(); 567 sal_Int32 nSelectPos = m_xLbRange->get_selected_index(); 568 bool bColName = nSelectPos != -1 && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataCol; 569 NameRangeMap::const_iterator itr = aRangeMap.find(aRangeStr); 570 if (itr == aRangeMap.end()) 571 return; 572 const ScRange& rRange = itr->second; 573 574 ScRangePair* pPair = nullptr; 575 bool bFound = false; 576 if ( bColName && (pPair = xColNameRanges->Find( rRange )) != nullptr ) 577 bFound = true; 578 else if ( !bColName && (pPair = xRowNameRanges->Find( rRange )) != nullptr ) 579 bFound = true; 580 if ( bFound ) 581 { 582 OUString aStrDelMsg = ScResId( STR_QUERY_DELENTRY ); 583 OUString aMsg = aStrDelMsg.getToken( 0, '#' ) 584 + aRangeStr 585 + aStrDelMsg.getToken( 1, '#' ); 586 587 if (RET_YES == QUERYBOX(m_xDialog.get(), aMsg)) 588 { 589 if ( bColName ) 590 xColNameRanges->Remove( *pPair ); 591 else 592 xRowNameRanges->Remove( *pPair ); 593 594 UpdateNames(); 595 const sal_Int32 nCnt = m_xLbRange->n_children(); 596 if ( nSelectPos >= nCnt ) 597 { 598 if ( nCnt ) 599 nSelectPos = nCnt - 1; 600 else 601 nSelectPos = 0; 602 } 603 m_xLbRange->select(nSelectPos); 604 if (nSelectPos && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataDelim) 605 m_xLbRange->select( --nSelectPos ); // ---Row--- 606 607 m_xLbRange->grab_focus(); 608 m_xBtnAdd->set_sensitive(false); 609 m_xBtnRemove->set_sensitive(false); 610 m_xEdAssign->SetText( EMPTY_OUSTRING ); 611 theCurArea = theCurData = ScRange(); 612 m_xBtnColHead->set_active(true); 613 m_xBtnRowHead->set_active(false); 614 m_xEdAssign2->SetText( EMPTY_OUSTRING ); 615 Range1SelectHdl( *m_xLbRange ); 616 } 617 } 618 } 619 620 // handler called when a row in the listbox is selected, updates form input fields 621 IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range1SelectHdl, weld::TreeView&, void) 622 { 623 sal_Int32 nSelectPos = m_xLbRange->get_selected_index(); 624 const sal_Int32 nCnt = m_xLbRange->n_children(); 625 sal_uInt16 nMoves = 0; 626 while (nSelectPos != -1 && nSelectPos < nCnt && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataDelim) 627 { // skip Delimiter 628 ++nMoves; 629 ++nSelectPos; 630 } 631 OUString aRangeStr = m_xLbRange->get_selected_text(); 632 if ( nMoves ) 633 { 634 if ( nSelectPos > 1 && nSelectPos >= nCnt ) 635 { // if entries exist before the " --- Row --- " Delimiter then 636 // do not stop at the delimiter 637 nSelectPos = nCnt - 2; 638 m_xLbRange->select(nSelectPos); 639 aRangeStr = m_xLbRange->get_selected_text(); 640 } 641 else if ( nSelectPos > 2 && nSelectPos < nCnt && !aRangeStr.isEmpty() 642 && aRangeStr == m_xEdAssign->GetText() ) 643 { // move upwards instead of below to the previous position 644 nSelectPos -= 2; 645 m_xLbRange->select( nSelectPos ); 646 aRangeStr = m_xLbRange->get_selected_text(); 647 } 648 else 649 m_xLbRange->select(nSelectPos); 650 } 651 NameRangeMap::const_iterator itr = aRangeMap.find(aRangeStr); 652 if ( itr != aRangeMap.end() ) 653 { 654 bool bColName = m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataCol; 655 UpdateRangeData( itr->second, bColName ); 656 m_xBtnAdd->set_sensitive(false); 657 m_xBtnRemove->set_sensitive(true); 658 } 659 else 660 { 661 if ( !m_xEdAssign->GetText().isEmpty() ) 662 { 663 if ( !m_xEdAssign2->GetText().isEmpty() ) 664 m_xBtnAdd->set_sensitive(true); 665 else 666 m_xBtnAdd->set_sensitive(false); 667 m_xBtnColHead->set_sensitive(true); 668 m_xBtnRowHead->set_sensitive(true); 669 m_xEdAssign2->GetWidget()->set_sensitive(true); 670 m_xRbAssign2->GetWidget()->set_sensitive(true); 671 } 672 else 673 { 674 m_xBtnAdd->set_sensitive(false); 675 m_xBtnColHead->set_sensitive(false); 676 m_xBtnRowHead->set_sensitive(false); 677 m_xEdAssign2->GetWidget()->set_sensitive(false); 678 m_xRbAssign2->GetWidget()->set_sensitive(false); 679 } 680 m_xBtnRemove->set_sensitive(false); 681 m_xEdAssign->GrabFocus(); 682 } 683 684 m_xEdAssign->GetWidget()->set_sensitive(true); 685 m_xRbAssign->GetWidget()->set_sensitive(true); 686 } 687 688 // handler called when the label range has changed 689 IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range1DataModifyHdl, formula::RefEdit&, void) 690 { 691 OUString aNewArea( m_xEdAssign->GetText() ); 692 bool bValid = false; 693 if (!aNewArea.isEmpty() && pDoc) 694 { 695 ScRange aRange; 696 if ( (aRange.ParseAny(aNewArea, pDoc, pDoc->GetAddressConvention() ) & ScRefFlags::VALID) == ScRefFlags::VALID) 697 { 698 SetColRowData( aRange ); 699 bValid = true; 700 } 701 } 702 if ( bValid ) 703 { 704 m_xBtnAdd->set_sensitive(true); 705 m_xBtnColHead->set_sensitive(true); 706 m_xBtnRowHead->set_sensitive(true); 707 m_xEdAssign2->GetWidget()->set_sensitive(true); 708 m_xRbAssign2->GetWidget()->set_sensitive(true); 709 } 710 else 711 { 712 m_xBtnAdd->set_sensitive(false); 713 m_xBtnColHead->set_sensitive(false); 714 m_xBtnRowHead->set_sensitive(false); 715 m_xEdAssign2->GetWidget()->set_sensitive(false); 716 m_xRbAssign2->GetWidget()->set_sensitive(false); 717 } 718 m_xBtnRemove->set_sensitive(false); 719 } 720 721 // handler called when the data range has changed 722 IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range2DataModifyHdl, formula::RefEdit&, void) 723 { 724 OUString aNewData( m_xEdAssign2->GetText() ); 725 if ( !aNewData.isEmpty() ) 726 { 727 ScRange aRange; 728 if ( (aRange.ParseAny(aNewData, pDoc, pDoc->GetAddressConvention() ) & ScRefFlags::VALID) == ScRefFlags::VALID) 729 { 730 AdjustColRowData( aRange ); 731 m_xBtnAdd->set_sensitive(true); 732 } 733 else 734 m_xBtnAdd->set_sensitive(false); 735 } 736 else 737 { 738 m_xBtnAdd->set_sensitive(false); 739 } 740 } 741 742 // handler for the radio button for columns, adjust ranges 743 IMPL_LINK_NOARG(ScColRowNameRangesDlg, ColClickHdl, weld::Button&, void) 744 { 745 if (m_xBtnColHead->get_active()) 746 { 747 if ( theCurArea.aStart.Row() == 0 && theCurArea.aEnd.Row() == pDoc->MaxRow() ) 748 { 749 theCurArea.aEnd.SetRow( pDoc->MaxRow() - 1 ); 750 OUString aStr(theCurArea.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, pDoc->GetAddressConvention())); 751 m_xEdAssign->SetText( aStr ); 752 } 753 ScRange aRange( theCurData ); 754 aRange.aStart.SetRow( std::min( static_cast<long>(theCurArea.aEnd.Row() + 1), static_cast<long>(pDoc->MaxRow()) ) ); 755 aRange.aEnd.SetRow( pDoc->MaxRow() ); 756 AdjustColRowData( aRange ); 757 } 758 } 759 760 // handler for the radio button for columns, adjust range 761 IMPL_LINK_NOARG(ScColRowNameRangesDlg, RowClickHdl, weld::Button&, void) 762 { 763 if (m_xBtnRowHead->get_active()) 764 { 765 if ( theCurArea.aStart.Col() == 0 && theCurArea.aEnd.Col() == pDoc->MaxCol() ) 766 { 767 theCurArea.aEnd.SetCol( pDoc->MaxCol() - 1 ); 768 OUString aStr(theCurArea.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, pDoc->GetAddressConvention())); 769 m_xEdAssign->SetText( aStr ); 770 } 771 ScRange aRange( theCurData ); 772 aRange.aStart.SetCol( static_cast<SCCOL>(std::min( static_cast<long>(theCurArea.aEnd.Col() + 1), static_cast<long>(pDoc->MaxCol()) )) ); 773 aRange.aEnd.SetCol( pDoc->MaxCol() ); 774 AdjustColRowData( aRange ); 775 } 776 } 777 778 IMPL_LINK( ScColRowNameRangesDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void ) 779 { 780 if (&rCtrl == m_xEdAssign.get()) 781 m_pEdActive = m_xEdAssign.get(); 782 else if (&rCtrl == m_xEdAssign2.get()) 783 m_pEdActive = m_xEdAssign2.get(); 784 else 785 m_pEdActive = nullptr; 786 787 if( m_pEdActive ) 788 m_pEdActive->SelectAll(); 789 } 790 791 IMPL_LINK( ScColRowNameRangesDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void ) 792 { 793 if (&rCtrl == m_xRbAssign.get()) 794 m_pEdActive = m_xEdAssign.get(); 795 else if (&rCtrl == m_xRbAssign2.get()) 796 m_pEdActive = m_xEdAssign2.get(); 797 else 798 m_pEdActive = nullptr; 799 800 if( m_pEdActive ) 801 m_pEdActive->SelectAll(); 802 } 803 804 IMPL_LINK_NOARG(ScColRowNameRangesDlg, LoseEditFocusHdl, formula::RefEdit&, void) 805 { 806 bDlgLostFocus = !m_xDialog->has_toplevel_focus(); 807 } 808 809 IMPL_LINK_NOARG(ScColRowNameRangesDlg, LoseButtonFocusHdl, formula::RefButton&, void) 810 { 811 bDlgLostFocus = !m_xDialog->has_toplevel_focus(); 812 } 813 814 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 815
