1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "../../include/pdfwindow/PDFWindow.h" 8 #include "../../include/pdfwindow/PWL_Wnd.h" 9 #include "../../include/pdfwindow/PWL_ListCtrl.h" 10 #include "../../include/pdfwindow/PWL_IconList.h" 11 #include "../../include/pdfwindow/PWL_Utils.h" 12 #include "../../include/pdfwindow/PWL_ScrollBar.h" 13 #include "../../include/pdfwindow/PWL_Label.h" 14 15 #define PWL_IconList_ITEM_ICON_LEFTMARGIN 10.0f 16 #define PWL_IconList_ITEM_WIDTH 20.0f 17 #define PWL_IconList_ITEM_HEIGHT 20.0f 18 #define PWL_IconList_ITEM_SPACE 4.0f 19 20 /* ------------------ CPWL_IconList_Item ------------------- */ 21 22 CPWL_IconList_Item::CPWL_IconList_Item() : 23 m_nIconIndex(-1), 24 m_pData(NULL), 25 m_bSelected(FALSE), 26 m_pText(NULL) 27 { 28 } 29 30 CPWL_IconList_Item::~CPWL_IconList_Item() 31 { 32 } 33 34 CFX_ByteString CPWL_IconList_Item::GetClassName() const 35 { 36 return "CPWL_IconList_Item"; 37 } 38 39 FX_FLOAT CPWL_IconList_Item::GetItemHeight(FX_FLOAT fLimitWidth) 40 { 41 return PWL_IconList_ITEM_HEIGHT; 42 } 43 44 void CPWL_IconList_Item::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device) 45 { 46 CPDF_Rect rcClient = GetClientRect(); 47 48 if (m_bSelected) 49 { 50 if (this->IsEnabled()) 51 { 52 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, 53 CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_SELBACKCOLOR,this->GetTransparency())); 54 } 55 else 56 { 57 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, 58 CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_LIGHTGRAYCOLOR,this->GetTransparency())); 59 } 60 } 61 62 CPDF_Rect rcIcon = rcClient; 63 rcIcon.left += PWL_IconList_ITEM_ICON_LEFTMARGIN; 64 rcIcon.right = rcIcon.left + PWL_IconList_ITEM_WIDTH; 65 66 CPWL_Utils::DrawIconAppStream(pDevice, pUser2Device, m_nIconIndex, rcIcon, 67 m_crIcon, m_pText->GetTextColor(), this->GetTransparency()); 68 } 69 70 void CPWL_IconList_Item::SetSelect(FX_BOOL bSelected) 71 { 72 m_bSelected = bSelected; 73 74 if (bSelected) 75 m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR); 76 else 77 m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR); 78 79 } 80 81 FX_BOOL CPWL_IconList_Item::IsSelected() const 82 { 83 return m_bSelected; 84 } 85 86 void CPWL_IconList_Item::CreateChildWnd(const PWL_CREATEPARAM & cp) 87 { 88 m_pText = new CPWL_Label; 89 90 PWL_CREATEPARAM lcp = cp; 91 lcp.pParentWnd = this; 92 lcp.dwFlags = PWS_CHILD | PWS_VISIBLE | PES_LEFT | PES_CENTER; 93 lcp.sTextColor = PWL_DEFAULT_BLACKCOLOR; 94 lcp.fFontSize = 12; 95 m_pText->Create(lcp); 96 } 97 98 void CPWL_IconList_Item::SetData(void* pData) 99 { 100 m_pData = pData; 101 } 102 103 void CPWL_IconList_Item::SetIcon(FX_INT32 nIconIndex) 104 { 105 m_nIconIndex = nIconIndex; 106 } 107 108 void CPWL_IconList_Item::SetText(const CFX_WideString& str) 109 { 110 m_pText->SetText(str); 111 } 112 113 CFX_WideString CPWL_IconList_Item::GetText() const 114 { 115 return m_pText->GetText(); 116 } 117 118 void CPWL_IconList_Item::RePosChildWnd() 119 { 120 CPDF_Rect rcClient = GetClientRect(); 121 122 rcClient.left += (PWL_IconList_ITEM_ICON_LEFTMARGIN + PWL_IconList_ITEM_WIDTH + PWL_IconList_ITEM_ICON_LEFTMARGIN); 123 124 m_pText->Move(rcClient, TRUE, FALSE); 125 } 126 127 void CPWL_IconList_Item::SetIconFillColor(const CPWL_Color& color) 128 { 129 m_crIcon = color; 130 } 131 132 void CPWL_IconList_Item::OnEnabled() 133 { 134 if (m_bSelected) 135 m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR); 136 else 137 m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR); 138 139 this->InvalidateRect(); 140 } 141 142 void CPWL_IconList_Item::OnDisabled() 143 { 144 m_pText->SetTextColor(PWL_DEFAULT_HEAVYGRAYCOLOR); 145 146 this->InvalidateRect(); 147 } 148 149 /* ----------------- CPWL_IconList_Content ----------------- */ 150 151 CPWL_IconList_Content::CPWL_IconList_Content(FX_INT32 nListCount) : 152 m_nSelectIndex(-1), 153 m_pNotify(NULL), 154 m_bEnableNotify(TRUE), 155 m_bMouseDown(FALSE), 156 m_nListCount(nListCount) 157 { 158 } 159 160 CPWL_IconList_Content::~CPWL_IconList_Content() 161 { 162 } 163 164 void CPWL_IconList_Content::CreateChildWnd(const PWL_CREATEPARAM & cp) 165 { 166 for (FX_INT32 i=0; i<m_nListCount; i++) 167 { 168 CPWL_IconList_Item* pNewItem = new CPWL_IconList_Item(); 169 170 PWL_CREATEPARAM icp = cp; 171 icp.pParentWnd = this; 172 icp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_NOREFRESHCLIP; 173 pNewItem->Create(icp); 174 } 175 176 this->SetItemSpace(PWL_IconList_ITEM_SPACE); 177 this->ResetContent(0); 178 179 if (CPWL_Wnd * pParent = this->GetParentWindow()) 180 { 181 CPDF_Rect rcScroll = this->GetScrollArea(); 182 this->GetScrollPos(); 183 184 PWL_SCROLL_INFO sInfo; 185 sInfo.fContentMin = rcScroll.bottom; 186 sInfo.fContentMax = rcScroll.top; 187 sInfo.fPlateWidth = GetClientRect().Height(); 188 sInfo.fSmallStep = 13.0f; 189 sInfo.fBigStep = sInfo.fPlateWidth; 190 191 pParent->OnNotify(this, PNM_SETSCROLLINFO, SBT_VSCROLL, (FX_INTPTR)&sInfo); 192 } 193 } 194 195 FX_BOOL CPWL_IconList_Content::OnLButtonDown(const CPDF_Point & point) 196 { 197 SetFocus(); 198 199 SetCapture(); 200 m_bMouseDown = TRUE; 201 202 FX_INT32 nItemIndex = FindItemIndex(point); 203 SetSelect(nItemIndex); 204 ScrollToItem(nItemIndex); 205 206 return TRUE; 207 } 208 209 FX_BOOL CPWL_IconList_Content::OnLButtonUp(const CPDF_Point & point) 210 { 211 m_bMouseDown = FALSE; 212 ReleaseCapture(); 213 214 return TRUE; 215 } 216 217 FX_BOOL CPWL_IconList_Content::OnMouseMove(const CPDF_Point & point) 218 { 219 if (m_bMouseDown) 220 { 221 FX_INT32 nItemIndex = FindItemIndex(point); 222 SetSelect(nItemIndex); 223 ScrollToItem(nItemIndex); 224 } 225 226 return TRUE; 227 } 228 229 FX_BOOL CPWL_IconList_Content::OnKeyDown(FX_WORD nChar) 230 { 231 switch (nChar) 232 { 233 case FWL_VKEY_Up: 234 if (m_nSelectIndex > 0) 235 { 236 FX_INT32 nItemIndex = m_nSelectIndex - 1; 237 SetSelect(nItemIndex); 238 ScrollToItem(nItemIndex); 239 } 240 return TRUE; 241 case FWL_VKEY_Down: 242 if (m_nSelectIndex < m_nListCount-1) 243 { 244 FX_INT32 nItemIndex = m_nSelectIndex + 1; 245 SetSelect(nItemIndex); 246 ScrollToItem(nItemIndex); 247 } 248 return TRUE; 249 } 250 251 return FALSE; 252 } 253 254 FX_INT32 CPWL_IconList_Content::FindItemIndex(const CPDF_Point& point) 255 { 256 FX_INT32 nIndex = 0; 257 for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++) 258 { 259 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i)) 260 { 261 CPDF_Rect rcWnd = pChild->ChildToParent(pChild->GetWindowRect()); 262 263 if (point.y < rcWnd.top) 264 { 265 nIndex = i; 266 } 267 } 268 } 269 270 return nIndex; 271 } 272 273 void CPWL_IconList_Content::ScrollToItem(FX_INT32 nItemIndex) 274 { 275 CPDF_Rect rcClient = GetClientRect(); 276 277 if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) 278 { 279 CPDF_Rect rcOrigin = pItem->GetWindowRect(); 280 CPDF_Rect rcWnd = pItem->ChildToParent(rcOrigin); 281 282 if (!(rcWnd.bottom > rcClient.bottom && rcWnd.top < rcClient.top)) 283 { 284 CPDF_Point ptScroll = GetScrollPos(); 285 286 if (rcWnd.top > rcClient.top) 287 { 288 ptScroll.y = rcOrigin.top; 289 } 290 else if (rcWnd.bottom < rcClient.bottom) 291 { 292 ptScroll.y = rcOrigin.bottom + rcClient.Height(); 293 } 294 295 this->SetScrollPos(ptScroll); 296 this->ResetFace(); 297 this->InvalidateRect(); 298 if (CPWL_Wnd* pParent = this->GetParentWindow()) 299 { 300 pParent->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y); 301 } 302 } 303 } 304 } 305 306 void CPWL_IconList_Content::SetSelect(FX_INT32 nIndex) 307 { 308 if (m_nSelectIndex != nIndex) 309 { 310 SelectItem(m_nSelectIndex, FALSE); 311 SelectItem(nIndex, TRUE); 312 m_nSelectIndex = nIndex; 313 314 if (IPWL_IconList_Notify* pNotify = GetNotify()) 315 pNotify->OnNoteListSelChanged(nIndex); 316 } 317 } 318 319 FX_INT32 CPWL_IconList_Content::GetSelect() const 320 { 321 return m_nSelectIndex; 322 } 323 324 IPWL_IconList_Notify* CPWL_IconList_Content::GetNotify() const 325 { 326 if (m_bEnableNotify) 327 return m_pNotify; 328 return NULL; 329 } 330 331 void CPWL_IconList_Content::SetNotify(IPWL_IconList_Notify* pNotify) 332 { 333 m_pNotify = pNotify; 334 } 335 336 void CPWL_IconList_Content::EnableNotify(FX_BOOL bNotify) 337 { 338 m_bEnableNotify = bNotify; 339 } 340 341 void CPWL_IconList_Content::SelectItem(FX_INT32 nItemIndex, FX_BOOL bSelect) 342 { 343 if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) 344 { 345 pItem->SetSelect(bSelect); 346 pItem->InvalidateRect(); 347 } 348 } 349 350 CPWL_IconList_Item* CPWL_IconList_Content::GetListItem(FX_INT32 nItemIndex) const 351 { 352 if (nItemIndex >= 0 && nItemIndex<m_aChildren.GetSize()) 353 { 354 if (CPWL_Wnd * pChild = m_aChildren.GetAt(nItemIndex)) 355 { 356 if (pChild->GetClassName() == "CPWL_IconList_Item") 357 { 358 return (CPWL_IconList_Item*)pChild; 359 } 360 } 361 } 362 363 return NULL; 364 } 365 366 void CPWL_IconList_Content::SetListData(FX_INT32 nItemIndex, void* pData) 367 { 368 if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) 369 pItem->SetData(pData); 370 } 371 372 void CPWL_IconList_Content::SetListIcon(FX_INT32 nItemIndex, FX_INT32 nIconIndex) 373 { 374 if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) 375 pItem->SetIcon(nIconIndex); 376 } 377 378 void CPWL_IconList_Content::SetListString(FX_INT32 nItemIndex, const CFX_WideString& str) 379 { 380 if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) 381 pItem->SetText(str); 382 } 383 384 CFX_WideString CPWL_IconList_Content::GetListString(FX_INT32 nItemIndex) const 385 { 386 if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) 387 return pItem->GetText(); 388 389 return L""; 390 } 391 392 void CPWL_IconList_Content::SetIconFillColor(const CPWL_Color& color) 393 { 394 for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++) 395 { 396 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i)) 397 { 398 if (pChild->GetClassName() == "CPWL_IconList_Item") 399 { 400 CPWL_IconList_Item* pItem = (CPWL_IconList_Item*)pChild; 401 pItem->SetIconFillColor(color); 402 pItem->InvalidateRect(); 403 } 404 } 405 } 406 407 } 408 409 /* -------------------- CPWL_IconList --------------------- */ 410 411 CPWL_IconList::CPWL_IconList(FX_INT32 nListCount) : 412 m_pListContent(NULL), 413 m_nListCount(nListCount) 414 { 415 } 416 417 CPWL_IconList::~CPWL_IconList() 418 { 419 } 420 421 void CPWL_IconList::RePosChildWnd() 422 { 423 CPWL_Wnd::RePosChildWnd(); 424 425 if (m_pListContent) 426 m_pListContent->Move(GetClientRect(), TRUE, FALSE); 427 } 428 429 void CPWL_IconList::CreateChildWnd(const PWL_CREATEPARAM & cp) 430 { 431 m_pListContent = new CPWL_IconList_Content(m_nListCount); 432 433 PWL_CREATEPARAM ccp = cp; 434 ccp.pParentWnd = this; 435 ccp.dwFlags = PWS_CHILD | PWS_VISIBLE; 436 m_pListContent->Create(ccp); 437 } 438 439 void CPWL_IconList::OnCreated() 440 { 441 if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) 442 { 443 pScrollBar->RemoveFlag(PWS_AUTOTRANSPARENT); 444 pScrollBar->SetTransparency(255); 445 pScrollBar->SetNotifyForever(TRUE); 446 } 447 } 448 449 void CPWL_IconList::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam) 450 { 451 CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); 452 453 if (wParam == SBT_VSCROLL) 454 { 455 switch (msg) 456 { 457 case PNM_SETSCROLLINFO: 458 if (PWL_SCROLL_INFO* pInfo = (PWL_SCROLL_INFO*)lParam) 459 { 460 if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) 461 { 462 if (pInfo->fContentMax - pInfo->fContentMin > pInfo->fPlateWidth) 463 { 464 if (!pScrollBar->IsVisible()) 465 { 466 pScrollBar->SetVisible(TRUE); 467 RePosChildWnd(); 468 } 469 else 470 { 471 } 472 } 473 else 474 { 475 if (pScrollBar->IsVisible()) 476 { 477 pScrollBar->SetVisible(FALSE); 478 RePosChildWnd(); 479 } 480 481 if (m_pListContent) 482 m_pListContent->SetScrollPos(CPDF_Point(0.0f,0.0f)); 483 } 484 485 pScrollBar->OnNotify(pWnd,PNM_SETSCROLLINFO,wParam,lParam); 486 } 487 } 488 return; 489 case PNM_SCROLLWINDOW: 490 if (m_pListContent) 491 { 492 m_pListContent->SetScrollPos(CPDF_Point(0.0f, *(FX_FLOAT*)lParam)); 493 m_pListContent->ResetFace(); 494 m_pListContent->InvalidateRect(NULL); 495 } 496 return; 497 case PNM_SETSCROLLPOS: 498 if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) 499 pScrollBar->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam); 500 return; 501 } 502 } 503 } 504 505 void CPWL_IconList::SetSelect(FX_INT32 nIndex) 506 { 507 m_pListContent->SetSelect(nIndex); 508 } 509 510 void CPWL_IconList::SetTopItem(FX_INT32 nIndex) 511 { 512 m_pListContent->ScrollToItem(nIndex); 513 } 514 515 FX_INT32 CPWL_IconList::GetSelect() const 516 { 517 return m_pListContent->GetSelect(); 518 } 519 520 void CPWL_IconList::SetNotify(IPWL_IconList_Notify* pNotify) 521 { 522 m_pListContent->SetNotify(pNotify); 523 } 524 525 void CPWL_IconList::EnableNotify(FX_BOOL bNotify) 526 { 527 m_pListContent->EnableNotify(bNotify); 528 } 529 530 void CPWL_IconList::SetListData(FX_INT32 nItemIndex, void* pData) 531 { 532 m_pListContent->SetListData(nItemIndex, pData); 533 } 534 535 void CPWL_IconList::SetListIcon(FX_INT32 nItemIndex, FX_INT32 nIconIndex) 536 { 537 m_pListContent->SetListIcon(nItemIndex, nIconIndex); 538 } 539 540 void CPWL_IconList::SetListString(FX_INT32 nItemIndex, const CFX_WideString& str) 541 { 542 m_pListContent->SetListString(nItemIndex, str); 543 } 544 545 CFX_WideString CPWL_IconList::GetListString(FX_INT32 nItemIndex) const 546 { 547 return m_pListContent->GetListString(nItemIndex); 548 } 549 550 void CPWL_IconList::SetIconFillColor(const CPWL_Color& color) 551 { 552 m_pListContent->SetIconFillColor(color); 553 } 554 555 FX_BOOL CPWL_IconList::OnMouseWheel(short zDelta, const CPDF_Point & point) 556 { 557 CPDF_Point ptScroll = m_pListContent->GetScrollPos(); 558 CPDF_Rect rcScroll = m_pListContent->GetScrollArea(); 559 CPDF_Rect rcContents = m_pListContent->GetClientRect(); 560 561 if (rcScroll.top - rcScroll.bottom > rcContents.Height()) 562 { 563 CPDF_Point ptNew = ptScroll; 564 565 if (zDelta > 0) 566 ptNew.y += 30; 567 else 568 ptNew.y -= 30; 569 570 if (ptNew.y > rcScroll.top) 571 ptNew.y = rcScroll.top; 572 if (ptNew.y < rcScroll.bottom + rcContents.Height()) 573 ptNew.y = rcScroll.bottom + rcContents.Height(); 574 if (ptNew.y < rcScroll.bottom) 575 ptNew.y = rcScroll.bottom; 576 577 if (ptNew.y != ptScroll.y) 578 { 579 m_pListContent->SetScrollPos(ptNew); 580 m_pListContent->ResetFace(); 581 m_pListContent->InvalidateRect(NULL); 582 583 if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) 584 pScrollBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptNew.y); 585 586 return TRUE; 587 } 588 } 589 590 return FALSE; 591 } 592 593