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 if (mpDeckTitleBar == &rWindow) 198 return FocusLocation(PC_DeckTitle, -1); 199 else if (&mpDeckTitleBar->GetToolBox() == &rWindow) 200 return FocusLocation(PC_DeckToolBox, -1); 201 202 // Search the panels. 203 for (sal_Int32 nIndex=0,nCount(maPanels.size()); nIndex<nCount; ++nIndex) 204 { 205 if (maPanels[nIndex] == &rWindow) 206 return FocusLocation(PC_PanelContent, nIndex); 207 TitleBar* pTitleBar = maPanels[nIndex]->GetTitleBar(); 208 if (pTitleBar == &rWindow) 209 return FocusLocation(PC_PanelTitle, nIndex); 210 if (pTitleBar!=NULL && &pTitleBar->GetToolBox()==&rWindow) 211 return FocusLocation(PC_PanelToolBox, nIndex); 212 } 213 214 // Search the buttons. 215 for (sal_Int32 nIndex=0,nCount(maButtons.size()); nIndex<nCount; ++nIndex) 216 if (maButtons[nIndex] == &rWindow) 217 return FocusLocation(PC_TabBar, nIndex); 218 219 return FocusLocation(PC_None, -1); 220 } 221 222 223 224 225 bool FocusManager::IsAnyPanelFocused (void) const 226 { 227 for (::std::vector<Panel*>::const_iterator iPanel(maPanels.begin()),iEnd(maPanels.end()); 228 iPanel!=iEnd; 229 ++iPanel) 230 { 231 if ((*iPanel)->HasFocus()) 232 return true; 233 else if ((*iPanel)->HasChildPathFocus()) 234 return true; 235 } 236 return false; 237 } 238 239 240 241 242 bool FocusManager::IsAnyButtonFocused (void) const 243 { 244 for (::std::vector<Button*>::const_iterator iButton(maButtons.begin()),iEnd(maButtons.end()); 245 iButton!=iEnd; 246 ++iButton) 247 { 248 if ((*iButton)->HasFocus()) 249 return true; 250 } 251 return false; 252 } 253 254 255 256 257 void FocusManager::FocusDeckTitle (void) 258 { 259 if (IsDeckTitleVisible()) 260 { 261 ToolBox& rToolBox = mpDeckTitleBar->GetToolBox(); 262 if (rToolBox.GetItemCount() > 0) 263 { 264 rToolBox.GrabFocus(); 265 rToolBox.Invalidate(); 266 } 267 } 268 else 269 FocusPanel(0); 270 } 271 272 273 274 275 bool FocusManager::IsDeckTitleVisible (void) const 276 { 277 return mpDeckTitleBar != NULL && mpDeckTitleBar->IsVisible(); 278 } 279 280 281 282 283 void FocusManager::FocusPanel (const sal_Int32 nPanelIndex) 284 { 285 if (nPanelIndex<0 || nPanelIndex>=maPanels.size()) 286 return; 287 Panel& rPanel (*maPanels[nPanelIndex]); 288 TitleBar* pTitleBar = rPanel.GetTitleBar(); 289 if (pTitleBar!=NULL && pTitleBar->IsVisible()) 290 { 291 rPanel.SetExpanded(true); 292 pTitleBar->GrabFocus(); 293 } 294 else 295 FocusPanelContent(nPanelIndex); 296 if (maShowPanelFunctor) 297 maShowPanelFunctor(rPanel); 298 } 299 300 301 302 303 void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex) 304 { 305 Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow()); 306 if (pWindow != NULL) 307 pWindow->GrabFocus(); 308 } 309 310 311 312 313 void FocusManager::FocusButton (const sal_Int32 nButtonIndex) 314 { 315 maButtons[nButtonIndex]->GrabFocus(); 316 maButtons[nButtonIndex]->Invalidate(); 317 } 318 319 320 321 322 void FocusManager::ClickButton (const sal_Int32 nButtonIndex) 323 { 324 maButtons[nButtonIndex]->Click(); 325 if (nButtonIndex > 0) 326 if ( ! maPanels.empty()) 327 FocusPanel(0); 328 maButtons[nButtonIndex]->GetParent()->Invalidate(); 329 } 330 331 332 333 334 void FocusManager::RemoveWindow (Window& rWindow) 335 { 336 ::std::vector<Panel*>::iterator iPanel (::std::find(maPanels.begin(), maPanels.end(), &rWindow)); 337 if (iPanel != maPanels.end()) 338 { 339 UnregisterWindow(rWindow); 340 if ((*iPanel)->GetTitleBar() != NULL) 341 { 342 UnregisterWindow(*(*iPanel)->GetTitleBar()); 343 UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 344 } 345 maPanels.erase(iPanel); 346 return; 347 } 348 349 ::std::vector<Button*>::iterator iButton (::std::find(maButtons.begin(), maButtons.end(), &rWindow)); 350 if (iButton != maButtons.end()) 351 { 352 UnregisterWindow(rWindow); 353 maButtons.erase(iButton); 354 return; 355 } 356 } 357 358 359 360 361 bool FocusManager::MoveFocusInsidePanel ( 362 const FocusLocation aFocusLocation, 363 const sal_Int32 nDirection) 364 { 365 const bool bHasToolBoxItem ( 366 maPanels[aFocusLocation.mnIndex]->GetTitleBar()->GetToolBox().GetItemCount() > 0); 367 switch (aFocusLocation.meComponent) 368 { 369 case PC_PanelTitle: 370 if (nDirection > 0 && bHasToolBoxItem) 371 maPanels[aFocusLocation.mnIndex]->GetTitleBar()->GetToolBox().GrabFocus(); 372 else 373 FocusPanelContent(aFocusLocation.mnIndex); 374 return true; 375 376 case PC_PanelToolBox: 377 if (nDirection < 0 && bHasToolBoxItem) 378 maPanels[aFocusLocation.mnIndex]->GetTitleBar()->GrabFocus(); 379 else 380 FocusPanelContent(aFocusLocation.mnIndex); 381 return true; 382 383 default: 384 return false; 385 } 386 } 387 388 389 390 391 void FocusManager::HandleKeyEvent ( 392 const KeyCode& rKeyCode, 393 const Window& rWindow) 394 { 395 const FocusLocation aLocation (GetFocusLocation(rWindow)); 396 397 switch (rKeyCode.GetCode()) 398 { 399 case KEY_SPACE: 400 switch (aLocation.meComponent) 401 { 402 case PC_PanelTitle: 403 // Toggle panel between expanded and collapsed. 404 maPanels[aLocation.mnIndex]->SetExpanded( ! maPanels[aLocation.mnIndex]->IsExpanded()); 405 break; 406 407 case PC_TabBar: 408 // Activate the button. 409 ClickButton(aLocation.mnIndex); 410 break; 411 412 default: 413 break; 414 } 415 return; 416 417 case KEY_RETURN: 418 switch (aLocation.meComponent) 419 { 420 case PC_DeckToolBox: 421 FocusButton(0); 422 break; 423 424 case PC_PanelTitle: 425 // Enter the panel. 426 FocusPanelContent(aLocation.mnIndex); 427 break; 428 429 case PC_TabBar: 430 // Activate the button. 431 ClickButton(aLocation.mnIndex); 432 break; 433 434 default: 435 break; 436 } 437 return; 438 439 case KEY_TAB: 440 switch (aLocation.meComponent) 441 { 442 case PC_PanelTitle: 443 case PC_PanelToolBox: 444 case PC_PanelContent: 445 if (rKeyCode.IsShift()) 446 MoveFocusInsidePanel(aLocation, -1); 447 else 448 MoveFocusInsidePanel(aLocation, +1); 449 break; 450 451 default: 452 break; 453 } 454 break; 455 456 case KEY_LEFT: 457 case KEY_UP: 458 switch (aLocation.meComponent) 459 { 460 case PC_PanelTitle: 461 case PC_PanelToolBox: 462 case PC_PanelContent: 463 // Go to previous panel or the deck title. 464 if (aLocation.mnIndex > 0) 465 FocusPanel(aLocation.mnIndex-1); 466 else if (IsDeckTitleVisible()) 467 FocusDeckTitle(); 468 else 469 FocusButton(maButtons.size()-1); 470 break; 471 472 case PC_DeckTitle: 473 case PC_DeckToolBox: 474 // Focus the last button. 475 FocusButton(maButtons.size()-1); 476 break; 477 478 case PC_TabBar: 479 // Go to previous tab bar item. 480 if (aLocation.mnIndex == 0) 481 FocusPanel(maPanels.size()-1); 482 else 483 FocusButton((aLocation.mnIndex + maButtons.size() - 1) % maButtons.size()); 484 break; 485 486 default: 487 break; 488 } 489 break; 490 491 case KEY_RIGHT: 492 case KEY_DOWN: 493 switch(aLocation.meComponent) 494 { 495 case PC_PanelTitle: 496 case PC_PanelToolBox: 497 case PC_PanelContent: 498 // Go to next panel. 499 if (aLocation.mnIndex < maPanels.size()-1) 500 FocusPanel(aLocation.mnIndex+1); 501 else 502 FocusButton(0); 503 break; 504 505 case PC_DeckTitle: 506 case PC_DeckToolBox: 507 // Focus the first panel. 508 FocusPanel(0); 509 break; 510 511 case PC_TabBar: 512 // Go to next tab bar item. 513 if (aLocation.mnIndex < maButtons.size()-1) 514 FocusButton(aLocation.mnIndex + 1); 515 else if (IsDeckTitleVisible()) 516 FocusDeckTitle(); 517 else 518 FocusPanel(0); 519 break; 520 521 default: 522 break; 523 } 524 break; 525 } 526 } 527 528 529 530 531 IMPL_LINK(FocusManager, WindowEventListener, VclSimpleEvent*, pEvent) 532 { 533 if (pEvent == NULL) 534 return 0; 535 536 if ( ! pEvent->ISA(VclWindowEvent)) 537 return 0; 538 539 VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); 540 Window* pSource = pWindowEvent->GetWindow(); 541 if (pSource == NULL) 542 return 0; 543 544 switch (pWindowEvent->GetId()) 545 { 546 case VCLEVENT_WINDOW_KEYINPUT: 547 { 548 KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); 549 HandleKeyEvent(pKeyEvent->GetKeyCode(), *pSource); 550 return 1; 551 } 552 553 case VCLEVENT_OBJECT_DYING: 554 RemoveWindow(*pSource); 555 return 1; 556 557 case VCLEVENT_WINDOW_GETFOCUS: 558 case VCLEVENT_WINDOW_LOSEFOCUS: 559 pSource->Invalidate(); 560 } 561 562 return 0; 563 } 564 565 566 567 568 IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) 569 { 570 if (pEvent == NULL) 571 return 0; 572 573 if ( ! pEvent->ISA(VclWindowEvent)) 574 return 0; 575 576 VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); 577 Window* pSource = pWindowEvent->GetWindow(); 578 if (pSource == NULL) 579 return 0; 580 581 switch (pWindowEvent->GetId()) 582 { 583 case VCLEVENT_WINDOW_KEYINPUT: 584 { 585 KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); 586 587 // Go up the window hierarchy to find the parent of the 588 // event source which is known to us. 589 Window* pWindow = pSource; 590 FocusLocation aLocation (PC_None, -1); 591 while (true) 592 { 593 if (pWindow == NULL) 594 break; 595 aLocation = GetFocusLocation(*pWindow); 596 if (aLocation.meComponent != PC_None) 597 break; 598 pWindow = pWindow->GetParent(); 599 } 600 601 if (aLocation.meComponent != PC_None) 602 { 603 switch (pKeyEvent->GetKeyCode().GetCode()) 604 { 605 case KEY_ESCAPE: 606 // Return focus back to the panel title. 607 FocusPanel(aLocation.mnIndex); 608 break; 609 610 default: 611 break; 612 } 613 } 614 break; 615 } 616 617 default: 618 break; 619 } 620 621 return 1; 622 } 623 624 625 } } // end of namespace sfx2::sidebar 626