| OLD | NEW |
| (Empty) |
| 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 "xfa/fwl/core/cfwl_edit.h" | |
| 8 | |
| 9 #include <algorithm> | |
| 10 #include <memory> | |
| 11 #include <utility> | |
| 12 #include <vector> | |
| 13 | |
| 14 #include "third_party/base/ptr_util.h" | |
| 15 #include "third_party/base/stl_util.h" | |
| 16 #include "xfa/fde/cfde_txtedtengine.h" | |
| 17 #include "xfa/fde/fde_gedevice.h" | |
| 18 #include "xfa/fde/fde_render.h" | |
| 19 #include "xfa/fde/ifde_txtedtpage.h" | |
| 20 #include "xfa/fgas/font/cfgas_gefont.h" | |
| 21 #include "xfa/fwl/core/cfwl_app.h" | |
| 22 #include "xfa/fwl/core/cfwl_caret.h" | |
| 23 #include "xfa/fwl/core/cfwl_event.h" | |
| 24 #include "xfa/fwl/core/cfwl_evtcheckword.h" | |
| 25 #include "xfa/fwl/core/cfwl_evttextchanged.h" | |
| 26 #include "xfa/fwl/core/cfwl_evtvalidate.h" | |
| 27 #include "xfa/fwl/core/cfwl_msgkey.h" | |
| 28 #include "xfa/fwl/core/cfwl_msgmouse.h" | |
| 29 #include "xfa/fwl/core/cfwl_themebackground.h" | |
| 30 #include "xfa/fwl/core/cfwl_themepart.h" | |
| 31 #include "xfa/fwl/core/cfwl_widgetmgr.h" | |
| 32 #include "xfa/fwl/core/ifwl_themeprovider.h" | |
| 33 #include "xfa/fxfa/xfa_ffdoc.h" | |
| 34 #include "xfa/fxfa/xfa_ffwidget.h" | |
| 35 #include "xfa/fxgraphics/cfx_path.h" | |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 const int kEditMargin = 3; | |
| 40 | |
| 41 bool FX_EDIT_ISLATINWORD(FX_WCHAR c) { | |
| 42 return c == 0x2D || (c <= 0x005A && c >= 0x0041) || | |
| 43 (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) || | |
| 44 c == 0x0027; | |
| 45 } | |
| 46 | |
| 47 void AddSquigglyPath(CFX_Path* pPathData, | |
| 48 FX_FLOAT fStartX, | |
| 49 FX_FLOAT fEndX, | |
| 50 FX_FLOAT fY, | |
| 51 FX_FLOAT fStep) { | |
| 52 pPathData->MoveTo(fStartX, fY); | |
| 53 int i = 1; | |
| 54 for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i) | |
| 55 pPathData->LineTo(fx, fY + (i & 1) * fStep); | |
| 56 } | |
| 57 | |
| 58 } // namespace | |
| 59 | |
| 60 CFWL_Edit::CFWL_Edit(const CFWL_App* app, | |
| 61 std::unique_ptr<CFWL_WidgetProperties> properties, | |
| 62 CFWL_Widget* pOuter) | |
| 63 : CFWL_Widget(app, std::move(properties), pOuter), | |
| 64 m_fVAlignOffset(0.0f), | |
| 65 m_fScrollOffsetX(0.0f), | |
| 66 m_fScrollOffsetY(0.0f), | |
| 67 m_bLButtonDown(false), | |
| 68 m_nSelStart(0), | |
| 69 m_nLimit(-1), | |
| 70 m_fFontSize(0), | |
| 71 m_bSetRange(false), | |
| 72 m_iMax(0xFFFFFFF), | |
| 73 m_iCurRecord(-1), | |
| 74 m_iMaxRecord(128) { | |
| 75 m_rtClient.Reset(); | |
| 76 m_rtEngine.Reset(); | |
| 77 m_rtStatic.Reset(); | |
| 78 | |
| 79 InitCaret(); | |
| 80 } | |
| 81 | |
| 82 CFWL_Edit::~CFWL_Edit() { | |
| 83 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) | |
| 84 HideCaret(nullptr); | |
| 85 ClearRecord(); | |
| 86 } | |
| 87 | |
| 88 FWL_Type CFWL_Edit::GetClassID() const { | |
| 89 return FWL_Type::Edit; | |
| 90 } | |
| 91 | |
| 92 CFX_RectF CFWL_Edit::GetWidgetRect() { | |
| 93 CFX_RectF rect = m_pProperties->m_rtWidget; | |
| 94 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
| 95 if (IsShowScrollBar(true)) { | |
| 96 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( | |
| 97 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
| 98 rect.width += *pfWidth; | |
| 99 rect.width += kEditMargin; | |
| 100 } | |
| 101 if (IsShowScrollBar(false)) { | |
| 102 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( | |
| 103 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
| 104 rect.height += *pfWidth; | |
| 105 rect.height += kEditMargin; | |
| 106 } | |
| 107 } | |
| 108 return rect; | |
| 109 } | |
| 110 | |
| 111 CFX_RectF CFWL_Edit::GetAutosizedWidgetRect() { | |
| 112 CFX_RectF rect; | |
| 113 if (m_EdtEngine.GetTextLength() > 0) { | |
| 114 CFX_SizeF sz = CalcTextSize( | |
| 115 m_EdtEngine.GetText(0, -1), m_pProperties->m_pThemeProvider, | |
| 116 !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine)); | |
| 117 rect.Set(0, 0, sz.x, sz.y); | |
| 118 } | |
| 119 InflateWidgetRect(rect); | |
| 120 return rect; | |
| 121 } | |
| 122 | |
| 123 void CFWL_Edit::SetStates(uint32_t dwStates) { | |
| 124 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) || | |
| 125 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
| 126 HideCaret(nullptr); | |
| 127 } | |
| 128 CFWL_Widget::SetStates(dwStates); | |
| 129 } | |
| 130 | |
| 131 void CFWL_Edit::Update() { | |
| 132 if (IsLocked()) | |
| 133 return; | |
| 134 if (!m_pProperties->m_pThemeProvider) | |
| 135 m_pProperties->m_pThemeProvider = GetAvailableTheme(); | |
| 136 | |
| 137 Layout(); | |
| 138 if (m_rtClient.IsEmpty()) | |
| 139 return; | |
| 140 | |
| 141 UpdateEditEngine(); | |
| 142 UpdateVAlignment(); | |
| 143 UpdateScroll(); | |
| 144 InitCaret(); | |
| 145 } | |
| 146 | |
| 147 FWL_WidgetHit CFWL_Edit::HitTest(FX_FLOAT fx, FX_FLOAT fy) { | |
| 148 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
| 149 if (IsShowScrollBar(true)) { | |
| 150 if (m_pVertScrollBar->GetWidgetRect().Contains(fx, fy)) | |
| 151 return FWL_WidgetHit::VScrollBar; | |
| 152 } | |
| 153 if (IsShowScrollBar(false)) { | |
| 154 if (m_pHorzScrollBar->GetWidgetRect().Contains(fx, fy)) | |
| 155 return FWL_WidgetHit::HScrollBar; | |
| 156 } | |
| 157 } | |
| 158 if (m_rtClient.Contains(fx, fy)) | |
| 159 return FWL_WidgetHit::Edit; | |
| 160 return FWL_WidgetHit::Unknown; | |
| 161 } | |
| 162 | |
| 163 void CFWL_Edit::AddSpellCheckObj(CFX_Path& PathData, | |
| 164 int32_t nStart, | |
| 165 int32_t nCount, | |
| 166 FX_FLOAT fOffSetX, | |
| 167 FX_FLOAT fOffSetY) { | |
| 168 FX_FLOAT fStartX = 0.0f; | |
| 169 FX_FLOAT fEndX = 0.0f; | |
| 170 FX_FLOAT fY = 0.0f; | |
| 171 FX_FLOAT fStep = 0.0f; | |
| 172 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 173 CFX_RectFArray rectArray; | |
| 174 CFX_RectF rectText; | |
| 175 const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams(); | |
| 176 FX_FLOAT fAsent = static_cast<FX_FLOAT>(txtEdtParams->pFont->GetAscent()) * | |
| 177 txtEdtParams->fFontSize / 1000; | |
| 178 pPage->CalcRangeRectArray(nStart, nCount, rectArray); | |
| 179 | |
| 180 for (int i = 0; i < rectArray.GetSize(); i++) { | |
| 181 rectText = rectArray.GetAt(i); | |
| 182 fY = rectText.top + fAsent + fOffSetY; | |
| 183 fStep = txtEdtParams->fFontSize / 16.0f; | |
| 184 fStartX = rectText.left + fOffSetX; | |
| 185 fEndX = fStartX + rectText.Width(); | |
| 186 AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep); | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void CFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics, | |
| 191 const CFX_Matrix* pMatrix) { | |
| 192 pGraphics->SaveGraphState(); | |
| 193 if (pMatrix) | |
| 194 pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix)); | |
| 195 | |
| 196 CFX_Color crLine(0xFFFF0000); | |
| 197 CFWL_EvtCheckWord checkWordEvent(this); | |
| 198 | |
| 199 CFX_ByteString sLatinWord; | |
| 200 CFX_Path pathSpell; | |
| 201 pathSpell.Create(); | |
| 202 | |
| 203 int32_t nStart = 0; | |
| 204 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; | |
| 205 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; | |
| 206 | |
| 207 CFX_WideString wsSpell = GetText(); | |
| 208 int32_t nContentLen = wsSpell.GetLength(); | |
| 209 for (int i = 0; i < nContentLen; i++) { | |
| 210 if (FX_EDIT_ISLATINWORD(wsSpell[i])) { | |
| 211 if (sLatinWord.IsEmpty()) | |
| 212 nStart = i; | |
| 213 sLatinWord += (FX_CHAR)wsSpell[i]; | |
| 214 continue; | |
| 215 } | |
| 216 checkWordEvent.bsWord = sLatinWord; | |
| 217 checkWordEvent.bCheckWord = true; | |
| 218 DispatchEvent(&checkWordEvent); | |
| 219 | |
| 220 if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) { | |
| 221 AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX, | |
| 222 fOffSetY); | |
| 223 } | |
| 224 sLatinWord.clear(); | |
| 225 } | |
| 226 | |
| 227 checkWordEvent.bsWord = sLatinWord; | |
| 228 checkWordEvent.bCheckWord = true; | |
| 229 DispatchEvent(&checkWordEvent); | |
| 230 | |
| 231 if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) { | |
| 232 AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX, | |
| 233 fOffSetY); | |
| 234 } | |
| 235 if (!pathSpell.IsEmpty()) { | |
| 236 CFX_RectF rtClip = m_rtEngine; | |
| 237 CFX_Matrix mt; | |
| 238 mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY); | |
| 239 if (pMatrix) { | |
| 240 pMatrix->TransformRect(rtClip); | |
| 241 mt.Concat(*pMatrix); | |
| 242 } | |
| 243 pGraphics->SetClipRect(rtClip); | |
| 244 pGraphics->SetStrokeColor(&crLine); | |
| 245 pGraphics->SetLineWidth(0); | |
| 246 pGraphics->StrokePath(&pathSpell, nullptr); | |
| 247 } | |
| 248 pGraphics->RestoreGraphState(); | |
| 249 } | |
| 250 | |
| 251 void CFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { | |
| 252 if (!pGraphics) | |
| 253 return; | |
| 254 if (!m_pProperties->m_pThemeProvider) | |
| 255 return; | |
| 256 if (m_rtClient.IsEmpty()) | |
| 257 return; | |
| 258 | |
| 259 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
| 260 if (!m_pWidgetMgr->IsFormDisabled()) | |
| 261 DrawTextBk(pGraphics, pTheme, pMatrix); | |
| 262 DrawContent(pGraphics, pTheme, pMatrix); | |
| 263 | |
| 264 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && | |
| 265 !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) { | |
| 266 DrawSpellCheck(pGraphics, pMatrix); | |
| 267 } | |
| 268 if (HasBorder()) | |
| 269 DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); | |
| 270 if (HasEdge()) | |
| 271 DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix); | |
| 272 } | |
| 273 | |
| 274 void CFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { | |
| 275 if (!pThemeProvider) | |
| 276 return; | |
| 277 if (m_pHorzScrollBar) | |
| 278 m_pHorzScrollBar->SetThemeProvider(pThemeProvider); | |
| 279 if (m_pVertScrollBar) | |
| 280 m_pVertScrollBar->SetThemeProvider(pThemeProvider); | |
| 281 if (m_pCaret) | |
| 282 m_pCaret->SetThemeProvider(pThemeProvider); | |
| 283 m_pProperties->m_pThemeProvider = pThemeProvider; | |
| 284 } | |
| 285 | |
| 286 void CFWL_Edit::SetText(const CFX_WideString& wsText) { | |
| 287 m_EdtEngine.SetText(wsText); | |
| 288 } | |
| 289 | |
| 290 int32_t CFWL_Edit::GetTextLength() const { | |
| 291 return m_EdtEngine.GetTextLength(); | |
| 292 } | |
| 293 | |
| 294 CFX_WideString CFWL_Edit::GetText() const { | |
| 295 return m_EdtEngine.GetText(0, -1); | |
| 296 } | |
| 297 | |
| 298 void CFWL_Edit::ClearText() { | |
| 299 m_EdtEngine.ClearText(); | |
| 300 } | |
| 301 | |
| 302 void CFWL_Edit::AddSelRange(int32_t nStart) { | |
| 303 m_EdtEngine.AddSelRange(nStart, -1); | |
| 304 } | |
| 305 | |
| 306 int32_t CFWL_Edit::CountSelRanges() const { | |
| 307 return m_EdtEngine.CountSelRanges(); | |
| 308 } | |
| 309 | |
| 310 int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t* nStart) const { | |
| 311 return m_EdtEngine.GetSelRange(nIndex, nStart); | |
| 312 } | |
| 313 | |
| 314 void CFWL_Edit::ClearSelections() { | |
| 315 m_EdtEngine.ClearSelection(); | |
| 316 } | |
| 317 | |
| 318 int32_t CFWL_Edit::GetLimit() const { | |
| 319 return m_nLimit; | |
| 320 } | |
| 321 | |
| 322 void CFWL_Edit::SetLimit(int32_t nLimit) { | |
| 323 m_nLimit = nLimit; | |
| 324 m_EdtEngine.SetLimit(nLimit); | |
| 325 } | |
| 326 | |
| 327 void CFWL_Edit::SetAliasChar(FX_WCHAR wAlias) { | |
| 328 m_EdtEngine.SetAliasChar(wAlias); | |
| 329 } | |
| 330 | |
| 331 bool CFWL_Edit::Copy(CFX_WideString& wsCopy) { | |
| 332 int32_t nCount = m_EdtEngine.CountSelRanges(); | |
| 333 if (nCount == 0) | |
| 334 return false; | |
| 335 | |
| 336 wsCopy.clear(); | |
| 337 int32_t nStart; | |
| 338 int32_t nLength; | |
| 339 for (int32_t i = 0; i < nCount; i++) { | |
| 340 nLength = m_EdtEngine.GetSelRange(i, &nStart); | |
| 341 wsCopy += m_EdtEngine.GetText(nStart, nLength); | |
| 342 } | |
| 343 return true; | |
| 344 } | |
| 345 | |
| 346 bool CFWL_Edit::Cut(CFX_WideString& wsCut) { | |
| 347 int32_t nCount = m_EdtEngine.CountSelRanges(); | |
| 348 if (nCount == 0) | |
| 349 return false; | |
| 350 | |
| 351 wsCut.clear(); | |
| 352 CFX_WideString wsTemp; | |
| 353 int32_t nStart, nLength; | |
| 354 for (int32_t i = 0; i < nCount; i++) { | |
| 355 nLength = m_EdtEngine.GetSelRange(i, &nStart); | |
| 356 wsTemp = m_EdtEngine.GetText(nStart, nLength); | |
| 357 wsCut += wsTemp; | |
| 358 wsTemp.clear(); | |
| 359 } | |
| 360 m_EdtEngine.Delete(0); | |
| 361 return true; | |
| 362 } | |
| 363 | |
| 364 bool CFWL_Edit::Paste(const CFX_WideString& wsPaste) { | |
| 365 int32_t nCaret = m_EdtEngine.GetCaretPos(); | |
| 366 int32_t iError = | |
| 367 m_EdtEngine.Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength()); | |
| 368 if (iError < 0) { | |
| 369 ProcessInsertError(iError); | |
| 370 return false; | |
| 371 } | |
| 372 return true; | |
| 373 } | |
| 374 | |
| 375 bool CFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) { | |
| 376 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) | |
| 377 return true; | |
| 378 return m_EdtEngine.Redo(pRecord); | |
| 379 } | |
| 380 | |
| 381 bool CFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) { | |
| 382 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) | |
| 383 return true; | |
| 384 return m_EdtEngine.Undo(pRecord); | |
| 385 } | |
| 386 | |
| 387 bool CFWL_Edit::Undo() { | |
| 388 if (!CanUndo()) | |
| 389 return false; | |
| 390 return Undo(m_DoRecords[m_iCurRecord--].get()); | |
| 391 } | |
| 392 | |
| 393 bool CFWL_Edit::Redo() { | |
| 394 if (!CanRedo()) | |
| 395 return false; | |
| 396 return Redo(m_DoRecords[++m_iCurRecord].get()); | |
| 397 } | |
| 398 | |
| 399 bool CFWL_Edit::CanUndo() { | |
| 400 return m_iCurRecord >= 0; | |
| 401 } | |
| 402 | |
| 403 bool CFWL_Edit::CanRedo() { | |
| 404 return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; | |
| 405 } | |
| 406 | |
| 407 void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) { | |
| 408 m_pOuter = pOuter; | |
| 409 } | |
| 410 | |
| 411 void CFWL_Edit::OnCaretChanged() { | |
| 412 if (m_rtEngine.IsEmpty()) | |
| 413 return; | |
| 414 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) | |
| 415 return; | |
| 416 | |
| 417 bool bRepaintContent = UpdateOffset(); | |
| 418 UpdateCaret(); | |
| 419 CFX_RectF rtInvalid; | |
| 420 rtInvalid.Set(0, 0, 0, 0); | |
| 421 bool bRepaintScroll = false; | |
| 422 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { | |
| 423 CFWL_ScrollBar* pScroll = UpdateScroll(); | |
| 424 if (pScroll) { | |
| 425 rtInvalid = pScroll->GetWidgetRect(); | |
| 426 bRepaintScroll = true; | |
| 427 } | |
| 428 } | |
| 429 if (bRepaintContent || bRepaintScroll) { | |
| 430 if (bRepaintContent) | |
| 431 rtInvalid.Union(m_rtEngine); | |
| 432 Repaint(&rtInvalid); | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 void CFWL_Edit::OnTextChanged(const FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) { | |
| 437 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask) | |
| 438 UpdateVAlignment(); | |
| 439 | |
| 440 CFX_RectF rtTemp; | |
| 441 GetClientRect(rtTemp); | |
| 442 | |
| 443 CFWL_EvtTextChanged event(this); | |
| 444 event.wsPrevText = ChangeInfo.wsPrevText; | |
| 445 DispatchEvent(&event); | |
| 446 | |
| 447 LayoutScrollBar(); | |
| 448 Repaint(&rtTemp); | |
| 449 } | |
| 450 | |
| 451 void CFWL_Edit::OnSelChanged() { | |
| 452 CFX_RectF rtTemp; | |
| 453 GetClientRect(rtTemp); | |
| 454 Repaint(&rtTemp); | |
| 455 } | |
| 456 | |
| 457 bool CFWL_Edit::OnPageLoad(int32_t nPageIndex) { | |
| 458 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex); | |
| 459 if (!pPage) | |
| 460 return false; | |
| 461 | |
| 462 pPage->LoadPage(nullptr, nullptr); | |
| 463 return true; | |
| 464 } | |
| 465 | |
| 466 bool CFWL_Edit::OnPageUnload(int32_t nPageIndex) { | |
| 467 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex); | |
| 468 if (!pPage) | |
| 469 return false; | |
| 470 | |
| 471 pPage->UnloadPage(nullptr); | |
| 472 return true; | |
| 473 } | |
| 474 | |
| 475 void CFWL_Edit::OnAddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord) { | |
| 476 AddDoRecord(std::move(pRecord)); | |
| 477 } | |
| 478 | |
| 479 bool CFWL_Edit::OnValidate(const CFX_WideString& wsText) { | |
| 480 CFWL_Widget* pDst = GetOuter(); | |
| 481 if (!pDst) | |
| 482 pDst = this; | |
| 483 | |
| 484 CFWL_EvtValidate event(this); | |
| 485 event.wsInsert = wsText; | |
| 486 event.bValidate = true; | |
| 487 DispatchEvent(&event); | |
| 488 return event.bValidate; | |
| 489 } | |
| 490 | |
| 491 void CFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) { | |
| 492 m_fScrollOffsetY = fScrollOffset; | |
| 493 } | |
| 494 | |
| 495 void CFWL_Edit::DrawTextBk(CFX_Graphics* pGraphics, | |
| 496 IFWL_ThemeProvider* pTheme, | |
| 497 const CFX_Matrix* pMatrix) { | |
| 498 CFWL_ThemeBackground param; | |
| 499 param.m_pWidget = this; | |
| 500 param.m_iPart = CFWL_Part::Background; | |
| 501 param.m_bStaticBackground = false; | |
| 502 param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly | |
| 503 ? CFWL_PartState_ReadOnly | |
| 504 : CFWL_PartState_Normal; | |
| 505 uint32_t dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled); | |
| 506 if (dwStates) | |
| 507 param.m_dwStates = CFWL_PartState_Disabled; | |
| 508 param.m_pGraphics = pGraphics; | |
| 509 param.m_matrix = *pMatrix; | |
| 510 param.m_rtPart = m_rtClient; | |
| 511 pTheme->DrawBackground(¶m); | |
| 512 | |
| 513 if (!IsShowScrollBar(true) || !IsShowScrollBar(false)) | |
| 514 return; | |
| 515 | |
| 516 CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect(); | |
| 517 | |
| 518 CFX_RectF rtStatic; | |
| 519 rtStatic.Set(m_rtClient.right() - rtScroll.height, | |
| 520 m_rtClient.bottom() - rtScroll.height, rtScroll.height, | |
| 521 rtScroll.height); | |
| 522 param.m_bStaticBackground = true; | |
| 523 param.m_bMaximize = true; | |
| 524 param.m_rtPart = rtStatic; | |
| 525 pTheme->DrawBackground(¶m); | |
| 526 } | |
| 527 | |
| 528 void CFWL_Edit::DrawContent(CFX_Graphics* pGraphics, | |
| 529 IFWL_ThemeProvider* pTheme, | |
| 530 const CFX_Matrix* pMatrix) { | |
| 531 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 532 if (!pPage) | |
| 533 return; | |
| 534 | |
| 535 pGraphics->SaveGraphState(); | |
| 536 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) | |
| 537 pGraphics->SaveGraphState(); | |
| 538 | |
| 539 CFX_RectF rtClip = m_rtEngine; | |
| 540 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; | |
| 541 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; | |
| 542 CFX_Matrix mt; | |
| 543 mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY); | |
| 544 if (pMatrix) { | |
| 545 pMatrix->TransformRect(rtClip); | |
| 546 mt.Concat(*pMatrix); | |
| 547 } | |
| 548 | |
| 549 bool bShowSel = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) || | |
| 550 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); | |
| 551 if (bShowSel) { | |
| 552 CFWL_Widget* pForm = m_pWidgetMgr->GetSystemFormWidget(this); | |
| 553 if (pForm) { | |
| 554 bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) != | |
| 555 FWL_WGTSTATE_Deactivated; | |
| 556 } | |
| 557 } | |
| 558 | |
| 559 int32_t nSelCount = m_EdtEngine.CountSelRanges(); | |
| 560 if (bShowSel && nSelCount > 0) { | |
| 561 int32_t nPageCharStart = pPage->GetCharStart(); | |
| 562 int32_t nPageCharCount = pPage->GetCharCount(); | |
| 563 int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1; | |
| 564 int32_t nCharCount; | |
| 565 int32_t nCharStart; | |
| 566 CFX_RectFArray rectArr; | |
| 567 int32_t i = 0; | |
| 568 for (i = 0; i < nSelCount; i++) { | |
| 569 nCharCount = m_EdtEngine.GetSelRange(i, &nCharStart); | |
| 570 int32_t nCharEnd = nCharStart + nCharCount - 1; | |
| 571 if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) | |
| 572 continue; | |
| 573 | |
| 574 int32_t nBgn = std::max(nCharStart, nPageCharStart); | |
| 575 int32_t nEnd = std::min(nCharEnd, nPageCharEnd); | |
| 576 pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1, | |
| 577 rectArr); | |
| 578 } | |
| 579 | |
| 580 int32_t nCount = rectArr.GetSize(); | |
| 581 CFX_Path path; | |
| 582 path.Create(); | |
| 583 for (i = 0; i < nCount; i++) { | |
| 584 rectArr[i].left += fOffSetX; | |
| 585 rectArr[i].top += fOffSetY; | |
| 586 path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width, | |
| 587 rectArr[i].height); | |
| 588 } | |
| 589 pGraphics->SetClipRect(rtClip); | |
| 590 | |
| 591 CFWL_ThemeBackground param; | |
| 592 param.m_pGraphics = pGraphics; | |
| 593 param.m_matrix = *pMatrix; | |
| 594 param.m_pWidget = this; | |
| 595 param.m_iPart = CFWL_Part::Background; | |
| 596 param.m_pPath = &path; | |
| 597 pTheme->DrawBackground(¶m); | |
| 598 } | |
| 599 | |
| 600 CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice(); | |
| 601 if (!pRenderDev) | |
| 602 return; | |
| 603 | |
| 604 std::unique_ptr<CFDE_RenderDevice> pRenderDevice( | |
| 605 new CFDE_RenderDevice(pRenderDev, false)); | |
| 606 std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext); | |
| 607 pRenderDevice->SetClipRect(rtClip); | |
| 608 pRenderContext->StartRender(pRenderDevice.get(), pPage, mt); | |
| 609 pRenderContext->DoRender(nullptr); | |
| 610 | |
| 611 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { | |
| 612 pGraphics->RestoreGraphState(); | |
| 613 CFX_Path path; | |
| 614 path.Create(); | |
| 615 int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1; | |
| 616 FX_FLOAT fStep = m_rtEngine.width / iLimit; | |
| 617 FX_FLOAT fLeft = m_rtEngine.left + 1; | |
| 618 for (int32_t i = 1; i < iLimit; i++) { | |
| 619 fLeft += fStep; | |
| 620 path.AddLine(fLeft, m_rtClient.top, fLeft, m_rtClient.bottom()); | |
| 621 } | |
| 622 | |
| 623 CFWL_ThemeBackground param; | |
| 624 param.m_pGraphics = pGraphics; | |
| 625 param.m_matrix = *pMatrix; | |
| 626 param.m_pWidget = this; | |
| 627 param.m_iPart = CFWL_Part::CombTextLine; | |
| 628 param.m_pPath = &path; | |
| 629 pTheme->DrawBackground(¶m); | |
| 630 } | |
| 631 pGraphics->RestoreGraphState(); | |
| 632 } | |
| 633 | |
| 634 void CFWL_Edit::UpdateEditEngine() { | |
| 635 UpdateEditParams(); | |
| 636 UpdateEditLayout(); | |
| 637 if (m_nLimit > -1) | |
| 638 m_EdtEngine.SetLimit(m_nLimit); | |
| 639 } | |
| 640 | |
| 641 void CFWL_Edit::UpdateEditParams() { | |
| 642 FDE_TXTEDTPARAMS params; | |
| 643 params.nHorzScale = 100; | |
| 644 params.fPlateWidth = m_rtEngine.width; | |
| 645 params.fPlateHeight = m_rtEngine.height; | |
| 646 if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout) | |
| 647 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL; | |
| 648 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout) | |
| 649 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical; | |
| 650 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars) | |
| 651 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial; | |
| 652 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine) | |
| 653 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve; | |
| 654 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes) | |
| 655 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes; | |
| 656 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab) | |
| 657 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab; | |
| 658 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) | |
| 659 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText; | |
| 660 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) | |
| 661 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight; | |
| 662 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) | |
| 663 params.dwMode |= FDE_TEXTEDITMODE_Validate; | |
| 664 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) | |
| 665 params.dwMode |= FDE_TEXTEDITMODE_Password; | |
| 666 | |
| 667 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) { | |
| 668 case FWL_STYLEEXT_EDT_HNear: { | |
| 669 params.dwAlignment |= FDE_TEXTEDITALIGN_Left; | |
| 670 break; | |
| 671 } | |
| 672 case FWL_STYLEEXT_EDT_HCenter: { | |
| 673 params.dwAlignment |= FDE_TEXTEDITALIGN_Center; | |
| 674 break; | |
| 675 } | |
| 676 case FWL_STYLEEXT_EDT_HFar: { | |
| 677 params.dwAlignment |= FDE_TEXTEDITALIGN_Right; | |
| 678 break; | |
| 679 } | |
| 680 default: | |
| 681 break; | |
| 682 } | |
| 683 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) { | |
| 684 case FWL_STYLEEXT_EDT_Justified: { | |
| 685 params.dwAlignment |= FDE_TEXTEDITALIGN_Justified; | |
| 686 break; | |
| 687 } | |
| 688 case FWL_STYLEEXT_EDT_Distributed: { | |
| 689 params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed; | |
| 690 break; | |
| 691 } | |
| 692 default: { | |
| 693 params.dwAlignment |= FDE_TEXTEDITALIGN_Normal; | |
| 694 break; | |
| 695 } | |
| 696 } | |
| 697 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { | |
| 698 params.dwMode |= FDE_TEXTEDITMODE_MultiLines; | |
| 699 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 && | |
| 700 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) { | |
| 701 params.dwMode |= | |
| 702 FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz; | |
| 703 } | |
| 704 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && | |
| 705 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) { | |
| 706 params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert; | |
| 707 } else { | |
| 708 params.fPlateHeight = 0x00FFFFFF; | |
| 709 } | |
| 710 } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == | |
| 711 0) { | |
| 712 params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz; | |
| 713 } | |
| 714 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || | |
| 715 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
| 716 params.dwMode |= FDE_TEXTEDITMODE_ReadOnly; | |
| 717 } | |
| 718 | |
| 719 FX_FLOAT* pFontSize = | |
| 720 static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize)); | |
| 721 if (!pFontSize) | |
| 722 return; | |
| 723 | |
| 724 m_fFontSize = *pFontSize; | |
| 725 uint32_t* pFontColor = | |
| 726 static_cast<uint32_t*>(GetThemeCapacity(CFWL_WidgetCapacity::TextColor)); | |
| 727 if (!pFontColor) | |
| 728 return; | |
| 729 | |
| 730 params.dwFontColor = *pFontColor; | |
| 731 FX_FLOAT* pLineHeight = | |
| 732 static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::LineHeight)); | |
| 733 if (!pLineHeight) | |
| 734 return; | |
| 735 | |
| 736 params.fLineSpace = *pLineHeight; | |
| 737 CFGAS_GEFont* pFont = | |
| 738 static_cast<CFGAS_GEFont*>(GetThemeCapacity(CFWL_WidgetCapacity::Font)); | |
| 739 if (!pFont) | |
| 740 return; | |
| 741 | |
| 742 params.pFont = pFont; | |
| 743 params.fFontSize = m_fFontSize; | |
| 744 params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace); | |
| 745 if (params.nLineCount <= 0) | |
| 746 params.nLineCount = 1; | |
| 747 params.fTabWidth = params.fFontSize * 1; | |
| 748 params.bTabEquidistant = true; | |
| 749 params.wLineBreakChar = L'\n'; | |
| 750 params.nCharRotation = 0; | |
| 751 params.pEventSink = this; | |
| 752 m_EdtEngine.SetEditParams(params); | |
| 753 } | |
| 754 | |
| 755 void CFWL_Edit::UpdateEditLayout() { | |
| 756 if (m_EdtEngine.GetTextLength() <= 0) | |
| 757 m_EdtEngine.SetTextByStream(nullptr); | |
| 758 | |
| 759 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 760 if (pPage) | |
| 761 pPage->UnloadPage(nullptr); | |
| 762 | |
| 763 m_EdtEngine.StartLayout(); | |
| 764 m_EdtEngine.DoLayout(nullptr); | |
| 765 m_EdtEngine.EndLayout(); | |
| 766 pPage = m_EdtEngine.GetPage(0); | |
| 767 if (pPage) | |
| 768 pPage->LoadPage(nullptr, nullptr); | |
| 769 } | |
| 770 | |
| 771 bool CFWL_Edit::UpdateOffset() { | |
| 772 CFX_RectF rtCaret; | |
| 773 m_EdtEngine.GetCaretRect(rtCaret); | |
| 774 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; | |
| 775 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; | |
| 776 rtCaret.Offset(fOffSetX, fOffSetY); | |
| 777 const CFX_RectF& rtEidt = m_rtEngine; | |
| 778 if (rtEidt.Contains(rtCaret)) { | |
| 779 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 780 if (!pPage) | |
| 781 return false; | |
| 782 | |
| 783 CFX_RectF rtFDE = pPage->GetContentsBox(); | |
| 784 rtFDE.Offset(fOffSetX, fOffSetY); | |
| 785 if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) { | |
| 786 m_fScrollOffsetX += rtFDE.right() - rtEidt.right(); | |
| 787 m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f); | |
| 788 } | |
| 789 if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) { | |
| 790 m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom(); | |
| 791 m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f); | |
| 792 } | |
| 793 return false; | |
| 794 } | |
| 795 | |
| 796 FX_FLOAT offsetX = 0.0; | |
| 797 FX_FLOAT offsetY = 0.0; | |
| 798 if (rtCaret.left < rtEidt.left) | |
| 799 offsetX = rtCaret.left - rtEidt.left; | |
| 800 if (rtCaret.right() > rtEidt.right()) | |
| 801 offsetX = rtCaret.right() - rtEidt.right(); | |
| 802 if (rtCaret.top < rtEidt.top) | |
| 803 offsetY = rtCaret.top - rtEidt.top; | |
| 804 if (rtCaret.bottom() > rtEidt.bottom()) | |
| 805 offsetY = rtCaret.bottom() - rtEidt.bottom(); | |
| 806 m_fScrollOffsetX += offsetX; | |
| 807 m_fScrollOffsetY += offsetY; | |
| 808 if (m_fFontSize > m_rtEngine.height) | |
| 809 m_fScrollOffsetY = 0; | |
| 810 return true; | |
| 811 } | |
| 812 | |
| 813 bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged) { | |
| 814 if (pScrollBar == m_pHorzScrollBar.get()) | |
| 815 m_fScrollOffsetX += fPosChanged; | |
| 816 else | |
| 817 m_fScrollOffsetY += fPosChanged; | |
| 818 return true; | |
| 819 } | |
| 820 | |
| 821 void CFWL_Edit::UpdateVAlignment() { | |
| 822 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 823 if (!pPage) | |
| 824 return; | |
| 825 | |
| 826 const CFX_RectF& rtFDE = pPage->GetContentsBox(); | |
| 827 FX_FLOAT fOffsetY = 0.0f; | |
| 828 FX_FLOAT fSpaceAbove = 0.0f; | |
| 829 FX_FLOAT fSpaceBelow = 0.0f; | |
| 830 CFX_SizeF* pSpace = static_cast<CFX_SizeF*>( | |
| 831 GetThemeCapacity(CFWL_WidgetCapacity::SpaceAboveBelow)); | |
| 832 if (pSpace) { | |
| 833 fSpaceAbove = pSpace->x; | |
| 834 fSpaceBelow = pSpace->y; | |
| 835 } | |
| 836 if (fSpaceAbove < 0.1f) | |
| 837 fSpaceAbove = 0; | |
| 838 if (fSpaceBelow < 0.1f) | |
| 839 fSpaceBelow = 0; | |
| 840 | |
| 841 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) { | |
| 842 fOffsetY = (m_rtEngine.height - rtFDE.height) / 2; | |
| 843 if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 && | |
| 844 fSpaceAbove < fSpaceBelow) { | |
| 845 return; | |
| 846 } | |
| 847 fOffsetY += (fSpaceAbove - fSpaceBelow) / 2; | |
| 848 } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) { | |
| 849 fOffsetY = (m_rtEngine.height - rtFDE.height); | |
| 850 fOffsetY -= fSpaceBelow; | |
| 851 } else { | |
| 852 fOffsetY += fSpaceAbove; | |
| 853 } | |
| 854 m_fVAlignOffset = std::max(fOffsetY, 0.0f); | |
| 855 } | |
| 856 | |
| 857 void CFWL_Edit::UpdateCaret() { | |
| 858 CFX_RectF rtFDE; | |
| 859 m_EdtEngine.GetCaretRect(rtFDE); | |
| 860 | |
| 861 rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX, | |
| 862 m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); | |
| 863 CFX_RectF rtCaret; | |
| 864 rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height); | |
| 865 | |
| 866 CFX_RectF rtClient; | |
| 867 GetClientRect(rtClient); | |
| 868 rtCaret.Intersect(rtClient); | |
| 869 | |
| 870 if (rtCaret.left > rtClient.right()) { | |
| 871 FX_FLOAT right = rtCaret.right(); | |
| 872 rtCaret.left = rtClient.right() - 1; | |
| 873 rtCaret.width = right - rtCaret.left; | |
| 874 } | |
| 875 | |
| 876 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && !rtCaret.IsEmpty()) | |
| 877 ShowCaret(&rtCaret); | |
| 878 else | |
| 879 HideCaret(&rtCaret); | |
| 880 } | |
| 881 | |
| 882 CFWL_ScrollBar* CFWL_Edit::UpdateScroll() { | |
| 883 bool bShowHorz = | |
| 884 m_pHorzScrollBar && | |
| 885 ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0); | |
| 886 bool bShowVert = | |
| 887 m_pVertScrollBar && | |
| 888 ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0); | |
| 889 if (!bShowHorz && !bShowVert) | |
| 890 return nullptr; | |
| 891 | |
| 892 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 893 if (!pPage) | |
| 894 return nullptr; | |
| 895 | |
| 896 const CFX_RectF& rtFDE = pPage->GetContentsBox(); | |
| 897 CFWL_ScrollBar* pRepaint = nullptr; | |
| 898 if (bShowHorz) { | |
| 899 CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect(); | |
| 900 if (rtScroll.width < rtFDE.width) { | |
| 901 m_pHorzScrollBar->LockUpdate(); | |
| 902 FX_FLOAT fRange = rtFDE.width - rtScroll.width; | |
| 903 m_pHorzScrollBar->SetRange(0.0f, fRange); | |
| 904 | |
| 905 FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetX, 0.0f), fRange); | |
| 906 m_pHorzScrollBar->SetPos(fPos); | |
| 907 m_pHorzScrollBar->SetTrackPos(fPos); | |
| 908 m_pHorzScrollBar->SetPageSize(rtScroll.width); | |
| 909 m_pHorzScrollBar->SetStepSize(rtScroll.width / 10); | |
| 910 m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Disabled); | |
| 911 m_pHorzScrollBar->UnlockUpdate(); | |
| 912 m_pHorzScrollBar->Update(); | |
| 913 pRepaint = m_pHorzScrollBar.get(); | |
| 914 } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) { | |
| 915 m_pHorzScrollBar->LockUpdate(); | |
| 916 m_pHorzScrollBar->SetRange(0, -1); | |
| 917 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled); | |
| 918 m_pHorzScrollBar->UnlockUpdate(); | |
| 919 m_pHorzScrollBar->Update(); | |
| 920 pRepaint = m_pHorzScrollBar.get(); | |
| 921 } | |
| 922 } | |
| 923 | |
| 924 if (bShowVert) { | |
| 925 CFX_RectF rtScroll = m_pVertScrollBar->GetWidgetRect(); | |
| 926 if (rtScroll.height < rtFDE.height) { | |
| 927 m_pVertScrollBar->LockUpdate(); | |
| 928 FX_FLOAT fStep = m_EdtEngine.GetEditParams()->fLineSpace; | |
| 929 FX_FLOAT fRange = std::max(rtFDE.height - m_rtEngine.height, fStep); | |
| 930 | |
| 931 m_pVertScrollBar->SetRange(0.0f, fRange); | |
| 932 FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetY, 0.0f), fRange); | |
| 933 m_pVertScrollBar->SetPos(fPos); | |
| 934 m_pVertScrollBar->SetTrackPos(fPos); | |
| 935 m_pVertScrollBar->SetPageSize(rtScroll.height); | |
| 936 m_pVertScrollBar->SetStepSize(fStep); | |
| 937 m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Disabled); | |
| 938 m_pVertScrollBar->UnlockUpdate(); | |
| 939 m_pVertScrollBar->Update(); | |
| 940 pRepaint = m_pVertScrollBar.get(); | |
| 941 } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) { | |
| 942 m_pVertScrollBar->LockUpdate(); | |
| 943 m_pVertScrollBar->SetRange(0, -1); | |
| 944 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled); | |
| 945 m_pVertScrollBar->UnlockUpdate(); | |
| 946 m_pVertScrollBar->Update(); | |
| 947 pRepaint = m_pVertScrollBar.get(); | |
| 948 } | |
| 949 } | |
| 950 return pRepaint; | |
| 951 } | |
| 952 | |
| 953 bool CFWL_Edit::IsShowScrollBar(bool bVert) { | |
| 954 bool bShow = | |
| 955 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) | |
| 956 ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == | |
| 957 FWL_WGTSTATE_Focused | |
| 958 : true; | |
| 959 if (bVert) { | |
| 960 return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) && | |
| 961 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) && | |
| 962 IsContentHeightOverflow(); | |
| 963 } | |
| 964 return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) && | |
| 965 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine); | |
| 966 } | |
| 967 | |
| 968 bool CFWL_Edit::IsContentHeightOverflow() { | |
| 969 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 970 if (!pPage) | |
| 971 return false; | |
| 972 return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f; | |
| 973 } | |
| 974 | |
| 975 int32_t CFWL_Edit::AddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord) { | |
| 976 int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords); | |
| 977 if (m_iCurRecord == nCount - 1) { | |
| 978 if (nCount == m_iMaxRecord) { | |
| 979 m_DoRecords.pop_front(); | |
| 980 m_iCurRecord--; | |
| 981 } | |
| 982 } else { | |
| 983 m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1, | |
| 984 m_DoRecords.end()); | |
| 985 } | |
| 986 | |
| 987 m_DoRecords.push_back(std::move(pRecord)); | |
| 988 m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; | |
| 989 return m_iCurRecord; | |
| 990 } | |
| 991 | |
| 992 void CFWL_Edit::Layout() { | |
| 993 GetClientRect(m_rtClient); | |
| 994 m_rtEngine = m_rtClient; | |
| 995 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( | |
| 996 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
| 997 if (!pfWidth) | |
| 998 return; | |
| 999 | |
| 1000 FX_FLOAT fWidth = *pfWidth; | |
| 1001 if (!m_pOuter) { | |
| 1002 CFX_RectF* pUIMargin = static_cast<CFX_RectF*>( | |
| 1003 GetThemeCapacity(CFWL_WidgetCapacity::UIMargin)); | |
| 1004 if (pUIMargin) { | |
| 1005 m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, | |
| 1006 pUIMargin->height); | |
| 1007 } | |
| 1008 } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) { | |
| 1009 CFWL_ThemePart part; | |
| 1010 part.m_pWidget = m_pOuter; | |
| 1011 CFX_RectF* pUIMargin = | |
| 1012 static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity( | |
| 1013 &part, CFWL_WidgetCapacity::UIMargin)); | |
| 1014 if (pUIMargin) { | |
| 1015 m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, | |
| 1016 pUIMargin->height); | |
| 1017 } | |
| 1018 } | |
| 1019 | |
| 1020 bool bShowVertScrollbar = IsShowScrollBar(true); | |
| 1021 bool bShowHorzScrollbar = IsShowScrollBar(false); | |
| 1022 if (bShowVertScrollbar) { | |
| 1023 InitVerticalScrollBar(); | |
| 1024 | |
| 1025 CFX_RectF rtVertScr; | |
| 1026 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
| 1027 rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth, | |
| 1028 m_rtClient.height); | |
| 1029 } else { | |
| 1030 rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth, | |
| 1031 m_rtClient.height); | |
| 1032 if (bShowHorzScrollbar) | |
| 1033 rtVertScr.height -= fWidth; | |
| 1034 m_rtEngine.width -= fWidth; | |
| 1035 } | |
| 1036 | |
| 1037 m_pVertScrollBar->SetWidgetRect(rtVertScr); | |
| 1038 m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Invisible); | |
| 1039 m_pVertScrollBar->Update(); | |
| 1040 } else if (m_pVertScrollBar) { | |
| 1041 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible); | |
| 1042 } | |
| 1043 | |
| 1044 if (bShowHorzScrollbar) { | |
| 1045 InitHorizontalScrollBar(); | |
| 1046 | |
| 1047 CFX_RectF rtHoriScr; | |
| 1048 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
| 1049 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin, | |
| 1050 m_rtClient.width, fWidth); | |
| 1051 } else { | |
| 1052 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth, | |
| 1053 m_rtClient.width, fWidth); | |
| 1054 if (bShowVertScrollbar) | |
| 1055 rtHoriScr.width -= fWidth; | |
| 1056 m_rtEngine.height -= fWidth; | |
| 1057 } | |
| 1058 m_pHorzScrollBar->SetWidgetRect(rtHoriScr); | |
| 1059 m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Invisible); | |
| 1060 m_pHorzScrollBar->Update(); | |
| 1061 } else if (m_pHorzScrollBar) { | |
| 1062 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible); | |
| 1063 } | |
| 1064 } | |
| 1065 | |
| 1066 void CFWL_Edit::LayoutScrollBar() { | |
| 1067 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) == | |
| 1068 0) { | |
| 1069 return; | |
| 1070 } | |
| 1071 | |
| 1072 FX_FLOAT* pfWidth = nullptr; | |
| 1073 bool bShowVertScrollbar = IsShowScrollBar(true); | |
| 1074 bool bShowHorzScrollbar = IsShowScrollBar(false); | |
| 1075 if (bShowVertScrollbar) { | |
| 1076 if (!m_pVertScrollBar) { | |
| 1077 pfWidth = static_cast<FX_FLOAT*>( | |
| 1078 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
| 1079 FX_FLOAT fWidth = pfWidth ? *pfWidth : 0; | |
| 1080 InitVerticalScrollBar(); | |
| 1081 CFX_RectF rtVertScr; | |
| 1082 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
| 1083 rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth, | |
| 1084 m_rtClient.height); | |
| 1085 } else { | |
| 1086 rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth, | |
| 1087 m_rtClient.height); | |
| 1088 if (bShowHorzScrollbar) | |
| 1089 rtVertScr.height -= fWidth; | |
| 1090 } | |
| 1091 m_pVertScrollBar->SetWidgetRect(rtVertScr); | |
| 1092 m_pVertScrollBar->Update(); | |
| 1093 } | |
| 1094 m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Invisible); | |
| 1095 } else if (m_pVertScrollBar) { | |
| 1096 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible); | |
| 1097 } | |
| 1098 | |
| 1099 if (bShowHorzScrollbar) { | |
| 1100 if (!m_pHorzScrollBar) { | |
| 1101 if (!pfWidth) { | |
| 1102 pfWidth = static_cast<FX_FLOAT*>( | |
| 1103 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
| 1104 } | |
| 1105 | |
| 1106 FX_FLOAT fWidth = pfWidth ? *pfWidth : 0; | |
| 1107 InitHorizontalScrollBar(); | |
| 1108 CFX_RectF rtHoriScr; | |
| 1109 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
| 1110 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin, | |
| 1111 m_rtClient.width, fWidth); | |
| 1112 } else { | |
| 1113 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth, | |
| 1114 m_rtClient.width, fWidth); | |
| 1115 if (bShowVertScrollbar) | |
| 1116 rtHoriScr.width -= (fWidth); | |
| 1117 } | |
| 1118 m_pHorzScrollBar->SetWidgetRect(rtHoriScr); | |
| 1119 m_pHorzScrollBar->Update(); | |
| 1120 } | |
| 1121 m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Invisible); | |
| 1122 } else if (m_pHorzScrollBar) { | |
| 1123 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible); | |
| 1124 } | |
| 1125 if (bShowVertScrollbar || bShowHorzScrollbar) | |
| 1126 UpdateScroll(); | |
| 1127 } | |
| 1128 | |
| 1129 void CFWL_Edit::DeviceToEngine(CFX_PointF& pt) { | |
| 1130 pt.x += m_fScrollOffsetX - m_rtEngine.left; | |
| 1131 pt.y += m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset; | |
| 1132 } | |
| 1133 | |
| 1134 void CFWL_Edit::InitVerticalScrollBar() { | |
| 1135 if (m_pVertScrollBar) | |
| 1136 return; | |
| 1137 | |
| 1138 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
| 1139 prop->m_dwStyleExes = FWL_STYLEEXT_SCB_Vert; | |
| 1140 prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible; | |
| 1141 prop->m_pParent = this; | |
| 1142 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; | |
| 1143 m_pVertScrollBar = | |
| 1144 pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this); | |
| 1145 } | |
| 1146 | |
| 1147 void CFWL_Edit::InitHorizontalScrollBar() { | |
| 1148 if (m_pHorzScrollBar) | |
| 1149 return; | |
| 1150 | |
| 1151 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
| 1152 prop->m_dwStyleExes = FWL_STYLEEXT_SCB_Horz; | |
| 1153 prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible; | |
| 1154 prop->m_pParent = this; | |
| 1155 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; | |
| 1156 m_pHorzScrollBar = | |
| 1157 pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this); | |
| 1158 } | |
| 1159 | |
| 1160 void CFWL_Edit::ShowCaret(CFX_RectF* pRect) { | |
| 1161 if (m_pCaret) { | |
| 1162 m_pCaret->ShowCaret(); | |
| 1163 if (!pRect->IsEmpty()) | |
| 1164 m_pCaret->SetWidgetRect(*pRect); | |
| 1165 Repaint(&m_rtEngine); | |
| 1166 return; | |
| 1167 } | |
| 1168 | |
| 1169 CFWL_Widget* pOuter = this; | |
| 1170 pRect->Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top); | |
| 1171 while (pOuter->GetOuter()) { | |
| 1172 pOuter = pOuter->GetOuter(); | |
| 1173 | |
| 1174 CFX_RectF rtOuter = pOuter->GetWidgetRect(); | |
| 1175 pRect->Offset(rtOuter.left, rtOuter.top); | |
| 1176 } | |
| 1177 | |
| 1178 CXFA_FFWidget* pXFAWidget = | |
| 1179 static_cast<CXFA_FFWidget*>(pOuter->GetLayoutItem()); | |
| 1180 if (!pXFAWidget) | |
| 1181 return; | |
| 1182 | |
| 1183 IXFA_DocEnvironment* pDocEnvironment = | |
| 1184 pXFAWidget->GetDoc()->GetDocEnvironment(); | |
| 1185 if (!pDocEnvironment) | |
| 1186 return; | |
| 1187 | |
| 1188 CFX_Matrix mt; | |
| 1189 pXFAWidget->GetRotateMatrix(mt); | |
| 1190 | |
| 1191 CFX_RectF rt(*pRect); | |
| 1192 mt.TransformRect(rt); | |
| 1193 pDocEnvironment->DisplayCaret(pXFAWidget, true, &rt); | |
| 1194 } | |
| 1195 | |
| 1196 void CFWL_Edit::HideCaret(CFX_RectF* pRect) { | |
| 1197 if (m_pCaret) { | |
| 1198 m_pCaret->HideCaret(); | |
| 1199 Repaint(&m_rtEngine); | |
| 1200 return; | |
| 1201 } | |
| 1202 | |
| 1203 CFWL_Widget* pOuter = this; | |
| 1204 while (pOuter->GetOuter()) | |
| 1205 pOuter = pOuter->GetOuter(); | |
| 1206 | |
| 1207 CXFA_FFWidget* pXFAWidget = | |
| 1208 static_cast<CXFA_FFWidget*>(pOuter->GetLayoutItem()); | |
| 1209 if (!pXFAWidget) | |
| 1210 return; | |
| 1211 | |
| 1212 IXFA_DocEnvironment* pDocEnvironment = | |
| 1213 pXFAWidget->GetDoc()->GetDocEnvironment(); | |
| 1214 if (!pDocEnvironment) | |
| 1215 return; | |
| 1216 | |
| 1217 pDocEnvironment->DisplayCaret(pXFAWidget, false, pRect); | |
| 1218 } | |
| 1219 | |
| 1220 bool CFWL_Edit::ValidateNumberChar(FX_WCHAR cNum) { | |
| 1221 if (!m_bSetRange) | |
| 1222 return true; | |
| 1223 | |
| 1224 CFX_WideString wsText = m_EdtEngine.GetText(0, -1); | |
| 1225 if (wsText.IsEmpty()) { | |
| 1226 if (cNum == L'0') | |
| 1227 return false; | |
| 1228 return true; | |
| 1229 } | |
| 1230 | |
| 1231 int32_t caretPos = m_EdtEngine.GetCaretPos(); | |
| 1232 if (CountSelRanges() == 0) { | |
| 1233 if (cNum == L'0' && caretPos == 0) | |
| 1234 return false; | |
| 1235 | |
| 1236 int32_t nLen = wsText.GetLength(); | |
| 1237 CFX_WideString l = wsText.Mid(0, caretPos); | |
| 1238 CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos); | |
| 1239 CFX_WideString wsNew = l + cNum + r; | |
| 1240 if (wsNew.GetInteger() <= m_iMax) | |
| 1241 return true; | |
| 1242 return false; | |
| 1243 } | |
| 1244 | |
| 1245 if (wsText.GetInteger() <= m_iMax) | |
| 1246 return true; | |
| 1247 return false; | |
| 1248 } | |
| 1249 | |
| 1250 void CFWL_Edit::InitCaret() { | |
| 1251 if (!m_pCaret) { | |
| 1252 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) { | |
| 1253 m_pCaret = pdfium::MakeUnique<CFWL_Caret>( | |
| 1254 m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this); | |
| 1255 m_pCaret->SetParent(this); | |
| 1256 m_pCaret->SetStates(m_pProperties->m_dwStates); | |
| 1257 } | |
| 1258 } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) == | |
| 1259 0) { | |
| 1260 m_pCaret.reset(); | |
| 1261 } | |
| 1262 } | |
| 1263 | |
| 1264 void CFWL_Edit::ClearRecord() { | |
| 1265 m_iCurRecord = -1; | |
| 1266 m_DoRecords.clear(); | |
| 1267 } | |
| 1268 | |
| 1269 void CFWL_Edit::ProcessInsertError(int32_t iError) { | |
| 1270 if (iError != -2) | |
| 1271 return; | |
| 1272 | |
| 1273 CFWL_Event textFullEvent(CFWL_Event::Type::TextFull, this); | |
| 1274 DispatchEvent(&textFullEvent); | |
| 1275 } | |
| 1276 | |
| 1277 void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { | |
| 1278 if (!pMessage) | |
| 1279 return; | |
| 1280 | |
| 1281 switch (pMessage->GetType()) { | |
| 1282 case CFWL_Message::Type::SetFocus: | |
| 1283 OnFocusChanged(pMessage, true); | |
| 1284 break; | |
| 1285 case CFWL_Message::Type::KillFocus: | |
| 1286 OnFocusChanged(pMessage, false); | |
| 1287 break; | |
| 1288 case CFWL_Message::Type::Mouse: { | |
| 1289 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); | |
| 1290 switch (pMsg->m_dwCmd) { | |
| 1291 case FWL_MouseCommand::LeftButtonDown: | |
| 1292 OnLButtonDown(pMsg); | |
| 1293 break; | |
| 1294 case FWL_MouseCommand::LeftButtonUp: | |
| 1295 OnLButtonUp(pMsg); | |
| 1296 break; | |
| 1297 case FWL_MouseCommand::LeftButtonDblClk: | |
| 1298 OnButtonDblClk(pMsg); | |
| 1299 break; | |
| 1300 case FWL_MouseCommand::Move: | |
| 1301 OnMouseMove(pMsg); | |
| 1302 break; | |
| 1303 case FWL_MouseCommand::RightButtonDown: | |
| 1304 DoButtonDown(pMsg); | |
| 1305 break; | |
| 1306 default: | |
| 1307 break; | |
| 1308 } | |
| 1309 break; | |
| 1310 } | |
| 1311 case CFWL_Message::Type::Key: { | |
| 1312 CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); | |
| 1313 if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown) | |
| 1314 OnKeyDown(pKey); | |
| 1315 else if (pKey->m_dwCmd == FWL_KeyCommand::Char) | |
| 1316 OnChar(pKey); | |
| 1317 break; | |
| 1318 } | |
| 1319 default: | |
| 1320 break; | |
| 1321 } | |
| 1322 CFWL_Widget::OnProcessMessage(pMessage); | |
| 1323 } | |
| 1324 | |
| 1325 void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) { | |
| 1326 if (!pEvent) | |
| 1327 return; | |
| 1328 if (pEvent->GetType() != CFWL_Event::Type::Scroll) | |
| 1329 return; | |
| 1330 | |
| 1331 CFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget; | |
| 1332 if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) || | |
| 1333 (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) { | |
| 1334 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); | |
| 1335 OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget), | |
| 1336 pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos); | |
| 1337 } | |
| 1338 } | |
| 1339 | |
| 1340 void CFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics, | |
| 1341 const CFX_Matrix* pMatrix) { | |
| 1342 DrawWidget(pGraphics, pMatrix); | |
| 1343 } | |
| 1344 | |
| 1345 void CFWL_Edit::DoButtonDown(CFWL_MsgMouse* pMsg) { | |
| 1346 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) | |
| 1347 SetFocus(true); | |
| 1348 | |
| 1349 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 1350 if (!pPage) | |
| 1351 return; | |
| 1352 | |
| 1353 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); | |
| 1354 DeviceToEngine(pt); | |
| 1355 bool bBefore = true; | |
| 1356 int32_t nIndex = pPage->GetCharIndex(pt, bBefore); | |
| 1357 if (nIndex < 0) | |
| 1358 nIndex = 0; | |
| 1359 | |
| 1360 m_EdtEngine.SetCaretPos(nIndex, bBefore); | |
| 1361 } | |
| 1362 | |
| 1363 void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { | |
| 1364 uint32_t dwStyleEx = GetStylesEx(); | |
| 1365 bool bRepaint = !!(dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret); | |
| 1366 if (bSet) { | |
| 1367 m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; | |
| 1368 | |
| 1369 UpdateVAlignment(); | |
| 1370 UpdateOffset(); | |
| 1371 UpdateCaret(); | |
| 1372 } else if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { | |
| 1373 m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; | |
| 1374 HideCaret(nullptr); | |
| 1375 if ((dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) { | |
| 1376 int32_t nSel = CountSelRanges(); | |
| 1377 if (nSel > 0) { | |
| 1378 ClearSelections(); | |
| 1379 bRepaint = true; | |
| 1380 } | |
| 1381 m_EdtEngine.SetCaretPos(0, true); | |
| 1382 UpdateOffset(); | |
| 1383 } | |
| 1384 ClearRecord(); | |
| 1385 } | |
| 1386 | |
| 1387 LayoutScrollBar(); | |
| 1388 if (!bRepaint) | |
| 1389 return; | |
| 1390 | |
| 1391 CFX_RectF rtInvalidate; | |
| 1392 rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width, | |
| 1393 m_pProperties->m_rtWidget.height); | |
| 1394 Repaint(&rtInvalidate); | |
| 1395 } | |
| 1396 | |
| 1397 void CFWL_Edit::OnLButtonDown(CFWL_MsgMouse* pMsg) { | |
| 1398 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) | |
| 1399 return; | |
| 1400 | |
| 1401 m_bLButtonDown = true; | |
| 1402 SetGrab(true); | |
| 1403 DoButtonDown(pMsg); | |
| 1404 int32_t nIndex = m_EdtEngine.GetCaretPos(); | |
| 1405 bool bRepaint = false; | |
| 1406 if (m_EdtEngine.CountSelRanges() > 0) { | |
| 1407 m_EdtEngine.ClearSelection(); | |
| 1408 bRepaint = true; | |
| 1409 } | |
| 1410 | |
| 1411 if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) { | |
| 1412 int32_t iStart = std::min(m_nSelStart, nIndex); | |
| 1413 int32_t iEnd = std::max(m_nSelStart, nIndex); | |
| 1414 m_EdtEngine.AddSelRange(iStart, iEnd - iStart); | |
| 1415 bRepaint = true; | |
| 1416 } else { | |
| 1417 m_nSelStart = nIndex; | |
| 1418 } | |
| 1419 if (bRepaint) | |
| 1420 Repaint(&m_rtEngine); | |
| 1421 } | |
| 1422 | |
| 1423 void CFWL_Edit::OnLButtonUp(CFWL_MsgMouse* pMsg) { | |
| 1424 m_bLButtonDown = false; | |
| 1425 SetGrab(false); | |
| 1426 } | |
| 1427 | |
| 1428 void CFWL_Edit::OnButtonDblClk(CFWL_MsgMouse* pMsg) { | |
| 1429 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 1430 if (!pPage) | |
| 1431 return; | |
| 1432 | |
| 1433 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); | |
| 1434 DeviceToEngine(pt); | |
| 1435 int32_t nCount = 0; | |
| 1436 int32_t nIndex = pPage->SelectWord(pt, nCount); | |
| 1437 if (nIndex < 0) | |
| 1438 return; | |
| 1439 | |
| 1440 m_EdtEngine.AddSelRange(nIndex, nCount); | |
| 1441 m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false); | |
| 1442 Repaint(&m_rtEngine); | |
| 1443 } | |
| 1444 | |
| 1445 void CFWL_Edit::OnMouseMove(CFWL_MsgMouse* pMsg) { | |
| 1446 if (m_nSelStart == -1 || !m_bLButtonDown) | |
| 1447 return; | |
| 1448 | |
| 1449 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
| 1450 if (!pPage) | |
| 1451 return; | |
| 1452 | |
| 1453 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); | |
| 1454 DeviceToEngine(pt); | |
| 1455 bool bBefore = true; | |
| 1456 int32_t nIndex = pPage->GetCharIndex(pt, bBefore); | |
| 1457 m_EdtEngine.SetCaretPos(nIndex, bBefore); | |
| 1458 nIndex = m_EdtEngine.GetCaretPos(); | |
| 1459 m_EdtEngine.ClearSelection(); | |
| 1460 | |
| 1461 if (nIndex == m_nSelStart) | |
| 1462 return; | |
| 1463 | |
| 1464 int32_t nLen = m_EdtEngine.GetTextLength(); | |
| 1465 if (m_nSelStart >= nLen) | |
| 1466 m_nSelStart = nLen; | |
| 1467 | |
| 1468 m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex), | |
| 1469 FXSYS_abs(nIndex - m_nSelStart)); | |
| 1470 } | |
| 1471 | |
| 1472 void CFWL_Edit::OnKeyDown(CFWL_MsgKey* pMsg) { | |
| 1473 FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone; | |
| 1474 bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift); | |
| 1475 bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl); | |
| 1476 uint32_t dwKeyCode = pMsg->m_dwKeyCode; | |
| 1477 switch (dwKeyCode) { | |
| 1478 case FWL_VKEY_Left: { | |
| 1479 MoveCaret = MC_Left; | |
| 1480 break; | |
| 1481 } | |
| 1482 case FWL_VKEY_Right: { | |
| 1483 MoveCaret = MC_Right; | |
| 1484 break; | |
| 1485 } | |
| 1486 case FWL_VKEY_Up: { | |
| 1487 MoveCaret = MC_Up; | |
| 1488 break; | |
| 1489 } | |
| 1490 case FWL_VKEY_Down: { | |
| 1491 MoveCaret = MC_Down; | |
| 1492 break; | |
| 1493 } | |
| 1494 case FWL_VKEY_Home: { | |
| 1495 MoveCaret = bCtrl ? MC_Home : MC_LineStart; | |
| 1496 break; | |
| 1497 } | |
| 1498 case FWL_VKEY_End: { | |
| 1499 MoveCaret = bCtrl ? MC_End : MC_LineEnd; | |
| 1500 break; | |
| 1501 } | |
| 1502 case FWL_VKEY_Insert: | |
| 1503 break; | |
| 1504 case FWL_VKEY_Delete: { | |
| 1505 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || | |
| 1506 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
| 1507 break; | |
| 1508 } | |
| 1509 int32_t nCaret = m_EdtEngine.GetCaretPos(); | |
| 1510 #if (_FX_OS_ == _FX_MACOSX_) | |
| 1511 m_EdtEngine.Delete(nCaret, true); | |
| 1512 #else | |
| 1513 m_EdtEngine.Delete(nCaret); | |
| 1514 #endif | |
| 1515 break; | |
| 1516 } | |
| 1517 case FWL_VKEY_F2: | |
| 1518 case FWL_VKEY_Tab: | |
| 1519 default: | |
| 1520 break; | |
| 1521 } | |
| 1522 if (MoveCaret != MC_MoveNone) | |
| 1523 m_EdtEngine.MoveCaretPos(MoveCaret, bShift, bCtrl); | |
| 1524 } | |
| 1525 | |
| 1526 void CFWL_Edit::OnChar(CFWL_MsgKey* pMsg) { | |
| 1527 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || | |
| 1528 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
| 1529 return; | |
| 1530 } | |
| 1531 | |
| 1532 int32_t iError = 0; | |
| 1533 FX_WCHAR c = static_cast<FX_WCHAR>(pMsg->m_dwKeyCode); | |
| 1534 int32_t nCaret = m_EdtEngine.GetCaretPos(); | |
| 1535 switch (c) { | |
| 1536 case FWL_VKEY_Back: | |
| 1537 m_EdtEngine.Delete(nCaret, true); | |
| 1538 break; | |
| 1539 case FWL_VKEY_NewLine: | |
| 1540 case FWL_VKEY_Escape: | |
| 1541 break; | |
| 1542 case FWL_VKEY_Tab: { | |
| 1543 iError = m_EdtEngine.Insert(nCaret, L"\t", 1); | |
| 1544 break; | |
| 1545 } | |
| 1546 case FWL_VKEY_Return: { | |
| 1547 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) { | |
| 1548 iError = m_EdtEngine.Insert(nCaret, L"\n", 1); | |
| 1549 } | |
| 1550 break; | |
| 1551 } | |
| 1552 default: { | |
| 1553 if (!m_pWidgetMgr->IsFormDisabled()) { | |
| 1554 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) { | |
| 1555 if (((pMsg->m_dwKeyCode < FWL_VKEY_0) && | |
| 1556 (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) || | |
| 1557 pMsg->m_dwKeyCode > FWL_VKEY_9) { | |
| 1558 break; | |
| 1559 } | |
| 1560 if (!ValidateNumberChar(c)) | |
| 1561 break; | |
| 1562 } | |
| 1563 } | |
| 1564 #if (_FX_OS_ == _FX_MACOSX_) | |
| 1565 if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) | |
| 1566 #else | |
| 1567 if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) | |
| 1568 #endif | |
| 1569 { | |
| 1570 break; | |
| 1571 } | |
| 1572 iError = m_EdtEngine.Insert(nCaret, &c, 1); | |
| 1573 break; | |
| 1574 } | |
| 1575 } | |
| 1576 if (iError < 0) | |
| 1577 ProcessInsertError(iError); | |
| 1578 } | |
| 1579 | |
| 1580 bool CFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar, | |
| 1581 CFWL_EvtScroll::Code dwCode, | |
| 1582 FX_FLOAT fPos) { | |
| 1583 CFX_SizeF fs; | |
| 1584 pScrollBar->GetRange(&fs.x, &fs.y); | |
| 1585 FX_FLOAT iCurPos = pScrollBar->GetPos(); | |
| 1586 FX_FLOAT fStep = pScrollBar->GetStepSize(); | |
| 1587 switch (dwCode) { | |
| 1588 case CFWL_EvtScroll::Code::Min: { | |
| 1589 fPos = fs.x; | |
| 1590 break; | |
| 1591 } | |
| 1592 case CFWL_EvtScroll::Code::Max: { | |
| 1593 fPos = fs.y; | |
| 1594 break; | |
| 1595 } | |
| 1596 case CFWL_EvtScroll::Code::StepBackward: { | |
| 1597 fPos -= fStep; | |
| 1598 if (fPos < fs.x + fStep / 2) { | |
| 1599 fPos = fs.x; | |
| 1600 } | |
| 1601 break; | |
| 1602 } | |
| 1603 case CFWL_EvtScroll::Code::StepForward: { | |
| 1604 fPos += fStep; | |
| 1605 if (fPos > fs.y - fStep / 2) { | |
| 1606 fPos = fs.y; | |
| 1607 } | |
| 1608 break; | |
| 1609 } | |
| 1610 case CFWL_EvtScroll::Code::PageBackward: { | |
| 1611 fPos -= pScrollBar->GetPageSize(); | |
| 1612 if (fPos < fs.x) { | |
| 1613 fPos = fs.x; | |
| 1614 } | |
| 1615 break; | |
| 1616 } | |
| 1617 case CFWL_EvtScroll::Code::PageForward: { | |
| 1618 fPos += pScrollBar->GetPageSize(); | |
| 1619 if (fPos > fs.y) { | |
| 1620 fPos = fs.y; | |
| 1621 } | |
| 1622 break; | |
| 1623 } | |
| 1624 case CFWL_EvtScroll::Code::Pos: | |
| 1625 case CFWL_EvtScroll::Code::TrackPos: | |
| 1626 case CFWL_EvtScroll::Code::None: | |
| 1627 break; | |
| 1628 case CFWL_EvtScroll::Code::EndScroll: | |
| 1629 return false; | |
| 1630 } | |
| 1631 if (iCurPos == fPos) | |
| 1632 return true; | |
| 1633 | |
| 1634 pScrollBar->SetPos(fPos); | |
| 1635 pScrollBar->SetTrackPos(fPos); | |
| 1636 UpdateOffset(pScrollBar, fPos - iCurPos); | |
| 1637 UpdateCaret(); | |
| 1638 | |
| 1639 CFX_RectF rect = GetWidgetRect(); | |
| 1640 CFX_RectF rtInvalidate; | |
| 1641 rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2); | |
| 1642 Repaint(&rtInvalidate); | |
| 1643 return true; | |
| 1644 } | |
| OLD | NEW |