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 #include "precompiled_sfx2.hxx" 23 24 #include "FocusManager.hxx" 25 #include "Panel.hxx" 26 #include "DeckTitleBar.hxx" 27 #include "sfx2/sidebar/Tools.hxx" 28 #include "TitleBar.hxx" 29 #include <vcl/button.hxx> 30 #include <vcl/toolbox.hxx> 31 #include <toolkit/helper/vclunohelper.hxx> 32 33 34 namespace sfx2 { namespace sidebar { 35 36 FocusManager::FocusLocation::FocusLocation (const PanelComponent eComponent, const sal_Int32 nIndex) 37 : meComponent(eComponent), 38 mnIndex(nIndex) 39 { 40 } 41 42 43 44 45 FocusManager::FocusManager (const ::boost::function<void(const Panel&)>& rShowPanelFunctor) 46 : mpDeckTitleBar(), 47 maPanels(), 48 maButtons(), 49 maShowPanelFunctor(rShowPanelFunctor) 50 { 51 } 52 53 54 55 56 FocusManager::~FocusManager (void) 57 { 58 Clear(); 59 } 60 61 62 63 64 void FocusManager::GrabFocus (void) 65 { 66 FocusDeckTitle(); 67 } 68 69 70 71 72 void FocusManager::Clear (void) 73 { 74 SetDeckTitle(NULL); 75 ClearPanels(); 76 ClearButtons(); 77 } 78 79 80 81 82 void FocusManager::ClearPanels (void) 83 { 84 ::std::vector<Panel*> aPanels; 85 aPanels.swap(maPanels); 86 for (::std::vector<Panel*>::iterator iPanel(aPanels.begin()),iEnd(aPanels.end()); 87 iPanel!=iEnd; 88 ++iPanel) 89 { 90 UnregisterWindow(**iPanel); 91 if ((*iPanel)->GetTitleBar() != NULL) 92 { 93 UnregisterWindow(*(*iPanel)->GetTitleBar()); 94 UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 95 } 96 97 (*iPanel)->RemoveChildEventListener(LINK(this, FocusManager, ChildEventListener)); 98 } 99 } 100 101 102 103 104 void FocusManager::ClearButtons (void) 105 { 106 ::std::vector<Button*> aButtons; 107 aButtons.swap(maButtons); 108 for (::std::vector<Button*>::iterator iButton(aButtons.begin()),iEnd(aButtons.end()); 109 iButton!=iEnd; 110 ++iButton) 111 { 112 UnregisterWindow(**iButton); 113 } 114 } 115 116 117 118 119 void FocusManager::SetDeckTitle (DeckTitleBar* pDeckTitleBar) 120 { 121 if (mpDeckTitleBar != NULL) 122 { 123 UnregisterWindow(*mpDeckTitleBar); 124 UnregisterWindow(mpDeckTitleBar->GetToolBox()); 125 } 126 mpDeckTitleBar = pDeckTitleBar; 127 128 if (mpDeckTitleBar != NULL) 129 { 130 RegisterWindow(*mpDeckTitleBar); 131 RegisterWindow(mpDeckTitleBar->GetToolBox()); 132 } 133 } 134 135 136 137 138 void FocusManager::SetPanels (const SharedPanelContainer& rPanels) 139 { 140 ClearPanels(); 141 for(SharedPanelContainer::const_iterator iPanel(rPanels.begin()),iEnd(rPanels.end()); 142 iPanel!=iEnd; 143 ++iPanel) 144 { 145 RegisterWindow(**iPanel); 146 if ((*iPanel)->GetTitleBar() != NULL) 147 { 148 RegisterWindow(*(*iPanel)->GetTitleBar()); 149 RegisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 150 } 151 152 // Register also as child event listener at the panel. 153 (*iPanel)->AddChildEventListener(LINK(this, FocusManager, ChildEventListener)); 154 155 maPanels.push_back(iPanel->get()); 156 } 157 } 158 159 160 161 162 void FocusManager::SetButtons (const ::std::vector<Button*>& rButtons) 163 { 164 ClearButtons(); 165 for (::std::vector<Button*>::const_iterator iButton(rButtons.begin()),iEnd(rButtons.end()); 166 iButton!=iEnd; 167 ++iButton) 168 { 169 RegisterWindow(**iButton); 170 maButtons.push_back(*iButton); 171 } 172 } 173 174 175 176 177 void FocusManager::RegisterWindow (Window& rWindow) 178 { 179 rWindow.AddEventListener(LINK(this, FocusManager, WindowEventListener)); 180 } 181 182 183 184 185 void FocusManager::UnregisterWindow (Window& rWindow) 186 { 187 rWindow.RemoveEventListener(LINK(this, FocusManager, WindowEventListener)); 188 } 189 190 191 192 193 FocusManager::FocusLocation FocusManager::GetFocusLocation (const Window& rWindow) const 194 { 195 // Check the deck title. 196 if (mpDeckTitleBar != NULL) 197 { 198 if (mpDeckTitleBar == &rWindow) 199 return FocusLocation(PC_DeckTitle, -1); 200 else if (&mpDeckTitleBar->GetToolBox() == &rWindow) 201 return FocusLocation(PC_DeckToolBox, -1); 202 } 203 204 // Search the panels. 205 for (sal_Int32 nIndex=0,nCount(maPanels.size()); nIndex<nCount; ++nIndex) 206 { 207 if (maPanels[nIndex] == &rWindow) 208 return FocusLocation(PC_PanelContent, nIndex); 209 TitleBar* pTitleBar = maPanels[nIndex]->GetTitleBar(); 210 if (pTitleBar == &rWindow) 211 return FocusLocation(PC_PanelTitle, nIndex); 212 if (pTitleBar!=NULL && &pTitleBar->GetToolBox()==&rWindow) 213 return FocusLocation(PC_PanelToolBox, nIndex); 214 } 215 216 // Search the buttons. 217 for (sal_Int32 nIndex=0,nCount(maButtons.size()); nIndex<nCount; ++nIndex) 218 if (maButtons[nIndex] == &rWindow) 219 return FocusLocation(PC_TabBar, nIndex); 220 221 return FocusLocation(PC_None, -1); 222 } 223 224 225 226 227 bool FocusManager::IsAnyPanelFocused (void) const 228 { 229 for (::std::vector<Panel*>::const_iterator iPanel(maPanels.begin()),iEnd(maPanels.end()); 230 iPanel!=iEnd; 231 ++iPanel) 232 { 233 if ((*iPanel)->HasFocus()) 234 return true; 235 else if ((*iPanel)->HasChildPathFocus()) 236 return true; 237 } 238 return false; 239 } 240 241 242 243 244 bool FocusManager::IsAnyButtonFocused (void) const 245 { 246 for (::std::vector<Button*>::const_iterator iButton(maButtons.begin()),iEnd(maButtons.end()); 247 iButton!=iEnd; 248 ++iButton) 249 { 250 if ((*iButton)->HasFocus()) 251 return true; 252 } 253 return false; 254 } 255 256 257 258 259 void FocusManager::FocusDeckTitle (void) 260 { 261 if (IsDeckTitleVisible()) 262 { 263 ToolBox& rToolBox = mpDeckTitleBar->GetToolBox(); 264 if (rToolBox.GetItemCount() > 0) 265 { 266 rToolBox.GrabFocus(); 267 rToolBox.Invalidate(); 268 } 269 } 270 else 271 FocusPanel(0); 272 } 273 274 275 276 277 bool FocusManager::IsDeckTitleVisible (void) const 278 { 279 return mpDeckTitleBar != NULL && mpDeckTitleBar->IsVisible(); 280 } 281 282 283 284 285 void FocusManager::FocusPanel (const sal_Int32 nPanelIndex) 286 { 287 if (nPanelIndex<0 || nPanelIndex>=static_cast<sal_Int32>(maPanels.size())) 288 return; 289 Panel& rPanel (*maPanels[nPanelIndex]); 290 TitleBar* pTitleBar = rPanel.GetTitleBar(); 291 if (pTitleBar!=NULL && pTitleBar->IsVisible()) 292 { 293 rPanel.SetExpanded(true); 294 pTitleBar->GrabFocus(); 295 } 296 else 297 FocusPanelContent(nPanelIndex); 298 if (maShowPanelFunctor) 299 maShowPanelFunctor(rPanel); 300 } 301 302 303 304 305 void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex) 306 { 307 Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow()); 308 if (pWindow != NULL) 309 pWindow->GrabFocus(); 310 } 311 312 313 314 315 void FocusManager::FocusButton (const sal_Int32 nButtonIndex) 316 { 317 maButtons[nButtonIndex]->GrabFocus(); 318 maButtons[nButtonIndex]->Invalidate(); 319 } 320 321 322 323 324 void FocusManager::ClickButton (const sal_Int32 nButtonIndex) 325 { 326 maButtons[nButtonIndex]->Click(); 327 if (nButtonIndex > 0) 328 if ( ! maPanels.empty()) 329 FocusPanel(0); 330 maButtons[nButtonIndex]->GetParent()->Invalidate(); 331 } 332 333 334 335 336 void FocusManager::RemoveWindow (Window& rWindow) 337 { 338 ::std::vector<Panel*>::iterator iPanel (::std::find(maPanels.begin(), maPanels.end(), &rWindow)); 339 if (iPanel != maPanels.end()) 340 { 341 UnregisterWindow(rWindow); 342 if ((*iPanel)->GetTitleBar() != NULL) 343 { 344 UnregisterWindow(*(*iPanel)->GetTitleBar()); 345 UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 346 } 347 maPanels.erase(iPanel); 348 return; 349 } 350 351 ::std::vector<Button*>::iterator iButton (::std::find(maButtons.begin(), maButtons.end(), &rWindow)); 352 if (iButton != maButtons.end()) 353 { 354 UnregisterWindow(rWindow); 355 maButtons.erase(iButton); 356 return; 357 } 358 } 359 360 361 362 363 bool FocusManager::MoveFocusInsidePanel ( 364 const FocusLocation aFocusLocation, 365 const sal_Int32 nDirection) 366 { 367 const bool bHasToolBoxItem ( 368 maPanels[aFocusLocation.mnIndex]->GetTitleBar()->GetToolBox().GetItemCount() > 0); 369 switch (aFocusLocation.meComponent) 370 { 371 case PC_PanelTitle: 372 if (nDirection > 0 && bHasToolBoxItem) 373 maPanels[aFocusLocation.mnIndex]->GetTitleBar()->GetToolBox().GrabFocus(); 374 else 375 FocusPanelContent(aFocusLocation.mnIndex); 376 return true; 377 378 case PC_PanelToolBox: 379 if (nDirection < 0 && bHasToolBoxItem) 380 maPanels[aFocusLocation.mnIndex]->GetTitleBar()->GrabFocus(); 381 else 382 FocusPanelContent(aFocusLocation.mnIndex); 383 return true; 384 385 default: 386 return false; 387 } 388 } 389 390 391 392 393 void FocusManager::HandleKeyEvent ( 394 const KeyCode& rKeyCode, 395 const Window& rWindow) 396 { 397 const FocusLocation aLocation (GetFocusLocation(rWindow)); 398 399 switch (rKeyCode.GetCode()) 400 { 401 case KEY_SPACE: 402 switch (aLocation.meComponent) 403 { 404 case PC_PanelTitle: 405 // Toggle panel between expanded and collapsed. 406 maPanels[aLocation.mnIndex]->SetExpanded( ! maPanels[aLocation.mnIndex]->IsExpanded()); 407 break; 408 409 case PC_TabBar: 410 // Activate the button. 411 ClickButton(aLocation.mnIndex); 412 break; 413 414 default: 415 break; 416 } 417 return; 418 419 case KEY_RETURN: 420 switch (aLocation.meComponent) 421 { 422 case PC_DeckToolBox: 423 FocusButton(0); 424 break; 425 426 case PC_PanelTitle: 427 // Enter the panel. 428 FocusPanelContent(aLocation.mnIndex); 429 break; 430 431 case PC_TabBar: 432 // Activate the button. 433 ClickButton(aLocation.mnIndex); 434 break; 435 436 default: 437 break; 438 } 439 return; 440 441 case KEY_TAB: 442 switch (aLocation.meComponent) 443 { 444 case PC_PanelTitle: 445 case PC_PanelToolBox: 446 case PC_PanelContent: 447 if (rKeyCode.IsShift()) 448 MoveFocusInsidePanel(aLocation, -1); 449 else 450 MoveFocusInsidePanel(aLocation, +1); 451 break; 452 453 default: 454 break; 455 } 456 break; 457 458 case KEY_LEFT: 459 case KEY_UP: 460 switch (aLocation.meComponent) 461 { 462 case PC_PanelTitle: 463 case PC_PanelToolBox: 464 case PC_PanelContent: 465 // Go to previous panel or the deck title. 466 if (aLocation.mnIndex > 0) 467 FocusPanel(aLocation.mnIndex-1); 468 else if (IsDeckTitleVisible()) 469 FocusDeckTitle(); 470 else 471 FocusButton(maButtons.size()-1); 472 break; 473 474 case PC_DeckTitle: 475 case PC_DeckToolBox: 476 // Focus the last button. 477 FocusButton(maButtons.size()-1); 478 break; 479 480 case PC_TabBar: 481 // Go to previous tab bar item. 482 if (aLocation.mnIndex == 0) 483 FocusPanel(maPanels.size()-1); 484 else 485 FocusButton((aLocation.mnIndex + maButtons.size() - 1) % maButtons.size()); 486 break; 487 488 default: 489 break; 490 } 491 break; 492 493 case KEY_RIGHT: 494 case KEY_DOWN: 495 switch(aLocation.meComponent) 496 { 497 case PC_PanelTitle: 498 case PC_PanelToolBox: 499 case PC_PanelContent: 500 // Go to next panel. 501 if (aLocation.mnIndex < static_cast<sal_Int32>(maPanels.size())-1) 502 FocusPanel(aLocation.mnIndex+1); 503 else 504 FocusButton(0); 505 break; 506 507 case PC_DeckTitle: 508 case PC_DeckToolBox: 509 // Focus the first panel. 510 FocusPanel(0); 511 break; 512 513 case PC_TabBar: 514 // Go to next tab bar item. 515 if (aLocation.mnIndex < static_cast<sal_Int32>(maButtons.size())-1) 516 FocusButton(aLocation.mnIndex + 1); 517 else if (IsDeckTitleVisible()) 518 FocusDeckTitle(); 519 else 520 FocusPanel(0); 521 break; 522 523 default: 524 break; 525 } 526 break; 527 } 528 } 529 530 531 532 533 IMPL_LINK(FocusManager, WindowEventListener, VclSimpleEvent*, pEvent) 534 { 535 if (pEvent == NULL) 536 return 0; 537 538 if ( ! pEvent->ISA(VclWindowEvent)) 539 return 0; 540 541 VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); 542 Window* pSource = pWindowEvent->GetWindow(); 543 if (pSource == NULL) 544 return 0; 545 546 switch (pWindowEvent->GetId()) 547 { 548 case VCLEVENT_WINDOW_KEYINPUT: 549 { 550 KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); 551 HandleKeyEvent(pKeyEvent->GetKeyCode(), *pSource); 552 return 1; 553 } 554 555 case VCLEVENT_OBJECT_DYING: 556 RemoveWindow(*pSource); 557 return 1; 558 559 case VCLEVENT_WINDOW_GETFOCUS: 560 case VCLEVENT_WINDOW_LOSEFOCUS: 561 pSource->Invalidate(); 562 } 563 564 return 0; 565 } 566 567 568 569 570 IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) 571 { 572 if (pEvent == NULL) 573 return 0; 574 575 if ( ! pEvent->ISA(VclWindowEvent)) 576 return 0; 577 578 VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); 579 Window* pSource = pWindowEvent->GetWindow(); 580 if (pSource == NULL) 581 return 0; 582 583 switch (pWindowEvent->GetId()) 584 { 585 case VCLEVENT_WINDOW_KEYINPUT: 586 { 587 KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); 588 589 // Go up the window hierarchy to find the parent of the 590 // event source which is known to us. 591 Window* pWindow = pSource; 592 FocusLocation aLocation (PC_None, -1); 593 while (true) 594 { 595 if (pWindow == NULL) 596 break; 597 aLocation = GetFocusLocation(*pWindow); 598 if (aLocation.meComponent != PC_None) 599 break; 600 pWindow = pWindow->GetParent(); 601 } 602 603 if (aLocation.meComponent != PC_None) 604 { 605 switch (pKeyEvent->GetKeyCode().GetCode()) 606 { 607 case KEY_ESCAPE: 608 // Return focus back to the panel title. 609 FocusPanel(aLocation.mnIndex); 610 break; 611 612 default: 613 break; 614 } 615 } 616 break; 617 } 618 619 default: 620 break; 621 } 622 623 return 1; 624 } 625 626 627 } } // end of namespace sfx2::sidebar 628