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