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 "sfx2/sidebar/Tools.hxx" 27 #include "TitleBar.hxx" 28 #include <vcl/button.hxx> 29 #include <vcl/toolbox.hxx> 30 #include <toolkit/helper/vclunohelper.hxx> 31 32 33 namespace sfx2 { namespace sidebar { 34 35 namespace 36 { 37 enum PanelComponent 38 { 39 PC_TitleBar, 40 PC_ToolBox, 41 PC_Content, 42 PC_None 43 }; 44 45 PanelComponent GetFocusedComponent (const Panel& rPanel) 46 { 47 if (rPanel.HasFocus()) 48 return PC_Content; 49 else if (rPanel.GetTitleBar() != NULL) 50 { 51 if (rPanel.GetTitleBar()->HasFocus()) 52 return PC_TitleBar; 53 else if (rPanel.GetTitleBar()->GetToolBox().HasFocus()) 54 return PC_ToolBox; 55 } 56 return PC_None; 57 } 58 } 59 60 61 FocusManager::FocusManager (void) 62 : maPanels(), 63 maButtons(), 64 mpTopLevelWindow(NULL) 65 { 66 } 67 68 69 70 71 FocusManager::~FocusManager (void) 72 { 73 Clear(); 74 } 75 76 77 78 79 void FocusManager::GrabFocus (void) 80 { 81 if ( ! maPanels.empty()) 82 FocusPanel(0); 83 } 84 85 86 87 88 void FocusManager::Clear (void) 89 { 90 ClearPanels(); 91 ClearButtons(); 92 } 93 94 95 96 void FocusManager::ClearPanels (void) 97 { 98 SetTopLevelWindow(NULL); 99 100 ::std::vector<Panel*> aPanels; 101 aPanels.swap(maPanels); 102 for (::std::vector<Panel*>::iterator iPanel(aPanels.begin()),iEnd(aPanels.end()); 103 iPanel!=iEnd; 104 ++iPanel) 105 { 106 UnregisterWindow(**iPanel); 107 if ((*iPanel)->GetTitleBar() != NULL) 108 { 109 UnregisterWindow(*(*iPanel)->GetTitleBar()); 110 UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 111 } 112 } 113 } 114 115 116 117 118 void FocusManager::ClearButtons (void) 119 { 120 ::std::vector<Window*> aButtons; 121 for (::std::vector<Window*>::iterator iButton(aButtons.begin()),iEnd(aButtons.end()); 122 iButton!=iEnd; 123 ++iButton) 124 { 125 UnregisterWindow(**iButton); 126 } 127 } 128 129 130 131 132 void FocusManager::SetPanels (const SharedPanelContainer& rPanels) 133 { 134 ClearPanels(); 135 for(SharedPanelContainer::const_iterator iPanel(rPanels.begin()),iEnd(rPanels.end()); 136 iPanel!=iEnd; 137 ++iPanel) 138 { 139 RegisterWindow(**iPanel); 140 if ((*iPanel)->GetTitleBar() != NULL) 141 { 142 RegisterWindow(*(*iPanel)->GetTitleBar()); 143 RegisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 144 } 145 maPanels.push_back(iPanel->get()); 146 } 147 148 RegisterTopLevelListener(); 149 } 150 151 152 153 154 void FocusManager::SetButtons (const ::std::vector<Button*>& rButtons) 155 { 156 ClearButtons(); 157 for (::std::vector<Button*>::const_iterator iButton(rButtons.begin()),iEnd(rButtons.end()); 158 iButton!=iEnd; 159 ++iButton) 160 { 161 RegisterWindow(**iButton); 162 maButtons.push_back(*iButton); 163 } 164 } 165 166 167 168 169 void FocusManager::RegisterWindow (Window& rWindow) 170 { 171 rWindow.AddEventListener(LINK(this, FocusManager, WindowEventListener)); 172 } 173 174 175 176 177 void FocusManager::UnregisterWindow (Window& rWindow) 178 { 179 rWindow.RemoveEventListener(LINK(this, FocusManager, WindowEventListener)); 180 } 181 182 183 184 185 void FocusManager::RegisterTopLevelListener (void) 186 { 187 if (maPanels.empty()) 188 return; 189 Window* pWindow = maPanels.front(); 190 while (pWindow != NULL && pWindow->GetParent()!=NULL) 191 { 192 pWindow = pWindow->GetParent(); 193 } 194 SetTopLevelWindow(pWindow); 195 } 196 197 198 199 200 void FocusManager::SetTopLevelWindow (Window* pWindow) 201 { 202 if (mpTopLevelWindow != pWindow) 203 { 204 if (mpTopLevelWindow != NULL) 205 { 206 UnregisterWindow(*mpTopLevelWindow); 207 mpTopLevelWindow->RemoveChildEventListener(LINK(this, FocusManager, WindowEventListener)); 208 } 209 mpTopLevelWindow = pWindow; 210 if (mpTopLevelWindow != NULL) 211 { 212 RegisterWindow(*mpTopLevelWindow); 213 mpTopLevelWindow->AddChildEventListener(LINK(this, FocusManager, WindowEventListener)); 214 } 215 } 216 } 217 218 219 220 221 sal_Int32 FocusManager::GetPanelIndex (const Window& rWindow) const 222 { 223 for (sal_Int32 nIndex=0,nCount(maPanels.size()); nIndex<nCount; ++nIndex) 224 { 225 if (maPanels[nIndex] == &rWindow) 226 return nIndex; 227 TitleBar* pTitleBar = maPanels[nIndex]->GetTitleBar(); 228 if (pTitleBar == &rWindow) 229 return nIndex; 230 if (pTitleBar!=NULL && &pTitleBar->GetToolBox()==&rWindow) 231 return nIndex; 232 } 233 return -1; 234 } 235 236 237 238 239 sal_Int32 FocusManager::GetButtonIndex (const Window& rWindow) const 240 { 241 for (sal_Int32 nIndex=0,nCount(maButtons.size()); nIndex<nCount; ++nIndex) 242 if (maButtons[nIndex] == &rWindow) 243 return nIndex; 244 return -1; 245 } 246 247 248 249 250 bool FocusManager::IsAnyPanelFocused (void) const 251 { 252 for (::std::vector<Panel*>::const_iterator iPanel(maPanels.begin()),iEnd(maPanels.end()); 253 iPanel!=iEnd; 254 ++iPanel) 255 { 256 if ((*iPanel)->HasFocus()) 257 return true; 258 else if ((*iPanel)->HasChildPathFocus()) 259 return true; 260 } 261 return false; 262 } 263 264 265 266 267 bool FocusManager::IsAnyButtonFocused (void) const 268 { 269 for (::std::vector<Button*>::const_iterator iButton(maButtons.begin()),iEnd(maButtons.end()); 270 iButton!=iEnd; 271 ++iButton) 272 { 273 if ((*iButton)->HasFocus()) 274 return true; 275 } 276 return false; 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 } 294 295 296 297 298 void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex) 299 { 300 Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow()); 301 if (pWindow != NULL) 302 pWindow->GrabFocus(); 303 } 304 305 306 307 308 void FocusManager::FocusButton (const sal_Int32 nButtonIndex) 309 { 310 maButtons[nButtonIndex]->GrabFocus(); 311 maButtons[nButtonIndex]->Invalidate(); 312 } 313 314 315 316 317 void FocusManager::ClickButton (const sal_Int32 nButtonIndex) 318 { 319 maButtons[nButtonIndex]->Click(); 320 if (nButtonIndex > 0) 321 if ( ! maPanels.empty()) 322 FocusPanel(0); 323 maButtons[nButtonIndex]->GetParent()->Invalidate(); 324 } 325 326 327 328 329 void FocusManager::RemoveWindow (Window& rWindow) 330 { 331 ::std::vector<Panel*>::iterator iPanel (::std::find(maPanels.begin(), maPanels.end(), &rWindow)); 332 if (iPanel != maPanels.end()) 333 { 334 UnregisterWindow(rWindow); 335 if ((*iPanel)->GetTitleBar() != NULL) 336 { 337 UnregisterWindow(*(*iPanel)->GetTitleBar()); 338 UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox()); 339 } 340 maPanels.erase(iPanel); 341 return; 342 } 343 344 ::std::vector<Button*>::iterator iButton (::std::find(maButtons.begin(), maButtons.end(), &rWindow)); 345 if (iButton != maButtons.end()) 346 { 347 UnregisterWindow(rWindow); 348 maButtons.erase(iButton); 349 return; 350 } 351 } 352 353 354 355 356 bool FocusManager::MoveFocusInsidePanel ( 357 const sal_Int32 nPanelIndex, 358 const sal_Int32 nDirection) 359 { 360 Panel& rPanel (*maPanels[nPanelIndex]); 361 switch (GetFocusedComponent(rPanel)) 362 { 363 case PC_TitleBar: 364 if (nDirection > 0) 365 rPanel.GetTitleBar()->GetToolBox().GrabFocus(); 366 else 367 FocusPanelContent(nPanelIndex); 368 return true; 369 370 case PC_ToolBox: 371 if (nDirection > 0) 372 FocusPanelContent(nPanelIndex); 373 else 374 rPanel.GetTitleBar()->GrabFocus(); 375 return true; 376 377 default: 378 return false; 379 } 380 } 381 382 383 384 385 long FocusManager::NotifyDockingWindowEvent (const KeyEvent& rKeyEvent) 386 { 387 switch(rKeyEvent.GetKeyCode().GetCode()) 388 { 389 case KEY_F6: 390 if (rKeyEvent.GetKeyCode().IsShift()) 391 { 392 if (IsAnyButtonFocused()) 393 { 394 FocusPanel(0); 395 return 1; 396 } 397 } 398 else 399 { 400 if (IsAnyPanelFocused()) 401 { 402 FocusButton(0); 403 return 1; 404 } 405 } 406 break; 407 } 408 return 0; 409 } 410 411 412 413 414 void FocusManager::HandleKeyEvent ( 415 const KeyCode& rKeyCode, 416 const Window& rWindow) 417 { 418 if (rKeyCode.GetModifier() != 0) 419 return; 420 421 const sal_Int32 nPanelIndex (GetPanelIndex(rWindow)); 422 // const bool bIsPanelTitleFocused (nPanelIndex>=0 && maPanels[nPanelIndex] != &rWindow); 423 // const bool bIsPanelToolBoxFocused (nPanelIndex>=0 && maPanels[nPanelIndex] != &rWindow); 424 sal_Int32 nButtonIndex (nPanelIndex==-1 ? GetButtonIndex(rWindow) : -1); 425 426 switch (rKeyCode.GetCode()) 427 { 428 case KEY_F6: 429 if (nPanelIndex >= 0) 430 FocusButton(0); 431 else 432 return; 433 break; 434 435 case KEY_SPACE: 436 if (nPanelIndex >= 0) 437 { 438 if (GetFocusedComponent(*maPanels[nPanelIndex]) == PC_TitleBar) 439 { 440 // Toggle the expansion state. 441 maPanels[nPanelIndex]->SetExpanded( ! maPanels[nPanelIndex]->IsExpanded()); 442 } 443 } 444 else if (nButtonIndex >= 0) 445 { 446 // Activate the button. 447 ClickButton(nButtonIndex); 448 } 449 return; 450 451 case KEY_RETURN: 452 if (nPanelIndex >= 0) 453 { 454 if (GetFocusedComponent(*maPanels[nPanelIndex]) == PC_TitleBar) 455 { 456 // Enter the panel. 457 FocusPanelContent(nPanelIndex); 458 } 459 } 460 else if (nButtonIndex >= 0) 461 { 462 // Activate the button. 463 ClickButton(nButtonIndex); 464 } 465 return; 466 467 case KEY_TAB: 468 if (nPanelIndex >= 0) 469 { 470 if (rKeyCode.IsShift()) 471 MoveFocusInsidePanel(nPanelIndex, -1); 472 else 473 MoveFocusInsidePanel(nPanelIndex, +1); 474 } 475 break; 476 477 case KEY_LEFT: 478 case KEY_UP: 479 // Go to previous element in focus ring. 480 if (nPanelIndex >= 0) 481 { 482 FocusPanel((nPanelIndex + maPanels.size() - 1) % maPanels.size()); 483 } 484 else if (nButtonIndex >= 0) 485 { 486 FocusButton((nButtonIndex + maButtons.size() - 1) % maButtons.size()); 487 } 488 break; 489 490 case KEY_RIGHT: 491 case KEY_DOWN: 492 // Go to next element in focus ring. 493 if (nPanelIndex >= 0) 494 { 495 FocusPanel((nPanelIndex + 1) % maPanels.size()); 496 } 497 else if (nButtonIndex >= 0) 498 { 499 FocusButton((nButtonIndex + 1) % maButtons.size()); 500 } 501 break; 502 } 503 } 504 505 506 507 508 void FocusManager::HandleTopLevelEvent (VclWindowEvent& rEvent) 509 { 510 switch (rEvent.GetId()) 511 { 512 case VCLEVENT_WINDOW_KEYINPUT: 513 { 514 KeyEvent* pKeyEvent = static_cast<KeyEvent*>(rEvent.GetData()); 515 switch (pKeyEvent->GetKeyCode().GetCode()) 516 { 517 case KEY_F6: 518 OSL_TRACE(""); 519 break; 520 } 521 } 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 if (pSource == mpTopLevelWindow) 542 HandleTopLevelEvent(*pWindowEvent); 543 else 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 return 0; 562 } 563 564 565 566 } } // end of namespace sfx2::sidebar 567