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