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