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