OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "xfa/fwl/core/cfwl_edit.h" | 7 #include "xfa/fwl/core/cfwl_edit.h" |
8 | 8 |
| 9 #include <algorithm> |
9 #include <memory> | 10 #include <memory> |
| 11 #include <utility> |
10 #include <vector> | 12 #include <vector> |
11 | 13 |
12 #include "third_party/base/ptr_util.h" | 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" |
13 | 36 |
14 namespace { | 37 namespace { |
15 | 38 |
16 IFWL_Edit* ToEdit(IFWL_Widget* widget) { | 39 const int kEditMargin = 3; |
17 return static_cast<IFWL_Edit*>(widget); | 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); |
18 } | 56 } |
19 | 57 |
20 } // namespace | 58 } // namespace |
21 | 59 |
22 CFWL_Edit::CFWL_Edit(const CFWL_App* app) : CFWL_Widget(app) {} | 60 CFWL_Edit::CFWL_Edit(const CFWL_App* app, |
23 | 61 std::unique_ptr<CFWL_WidgetProperties> properties, |
24 CFWL_Edit::~CFWL_Edit() {} | 62 CFWL_Widget* pOuter) |
25 | 63 : CFWL_Widget(app, std::move(properties), pOuter), |
26 void CFWL_Edit::Initialize() { | 64 m_fVAlignOffset(0.0f), |
27 ASSERT(!m_pIface); | 65 m_fScrollOffsetX(0.0f), |
28 | 66 m_fScrollOffsetY(0.0f), |
29 m_pIface = pdfium::MakeUnique<IFWL_Edit>( | 67 m_bLButtonDown(false), |
30 m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); | 68 m_nSelStart(0), |
31 | 69 m_nLimit(-1), |
32 CFWL_Widget::Initialize(); | 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 ShowCaret(false); |
| 85 ClearRecord(); |
| 86 } |
| 87 |
| 88 FWL_Type CFWL_Edit::GetClassID() const { |
| 89 return FWL_Type::Edit; |
| 90 } |
| 91 |
| 92 void CFWL_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 CFWL_Widget::GetWidgetRect(rect, true); |
| 124 } |
| 125 |
| 126 void CFWL_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 CFWL_Widget::SetStates(dwStates, bSet); |
| 132 } |
| 133 |
| 134 void CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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; |
33 } | 293 } |
34 | 294 |
35 void CFWL_Edit::SetText(const CFX_WideString& wsText) { | 295 void CFWL_Edit::SetText(const CFX_WideString& wsText) { |
36 if (GetWidget()) | 296 m_EdtEngine.SetText(wsText); |
37 ToEdit(GetWidget())->SetText(wsText); | 297 } |
| 298 |
| 299 int32_t CFWL_Edit::GetTextLength() const { |
| 300 return m_EdtEngine.GetTextLength(); |
38 } | 301 } |
39 | 302 |
40 void CFWL_Edit::GetText(CFX_WideString& wsText, | 303 void CFWL_Edit::GetText(CFX_WideString& wsText, |
41 int32_t nStart, | 304 int32_t nStart, |
42 int32_t nCount) const { | 305 int32_t nCount) const { |
43 if (GetWidget()) | 306 m_EdtEngine.GetText(wsText, nStart, nCount); |
44 ToEdit(GetWidget())->GetText(wsText, nStart, nCount); | 307 } |
| 308 |
| 309 void CFWL_Edit::ClearText() { |
| 310 m_EdtEngine.ClearText(); |
| 311 } |
| 312 |
| 313 void CFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) { |
| 314 m_EdtEngine.AddSelRange(nStart, nCount); |
45 } | 315 } |
46 | 316 |
47 int32_t CFWL_Edit::CountSelRanges() const { | 317 int32_t CFWL_Edit::CountSelRanges() const { |
48 return GetWidget() ? ToEdit(GetWidget())->CountSelRanges() : 0; | 318 return m_EdtEngine.CountSelRanges(); |
49 } | 319 } |
50 | 320 |
51 int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) const { | 321 int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) const { |
52 return GetWidget() ? ToEdit(GetWidget())->GetSelRange(nIndex, nStart) : 0; | 322 return m_EdtEngine.GetSelRange(nIndex, nStart); |
| 323 } |
| 324 |
| 325 void CFWL_Edit::ClearSelections() { |
| 326 m_EdtEngine.ClearSelection(); |
53 } | 327 } |
54 | 328 |
55 int32_t CFWL_Edit::GetLimit() const { | 329 int32_t CFWL_Edit::GetLimit() const { |
56 return GetWidget() ? ToEdit(GetWidget())->GetLimit() : -1; | 330 return m_nLimit; |
57 } | 331 } |
58 | 332 |
59 void CFWL_Edit::SetLimit(int32_t nLimit) { | 333 void CFWL_Edit::SetLimit(int32_t nLimit) { |
60 if (GetWidget()) | 334 m_nLimit = nLimit; |
61 ToEdit(GetWidget())->SetLimit(nLimit); | 335 m_EdtEngine.SetLimit(nLimit); |
62 } | 336 } |
63 | 337 |
64 void CFWL_Edit::SetAliasChar(FX_WCHAR wAlias) { | 338 void CFWL_Edit::SetAliasChar(FX_WCHAR wAlias) { |
65 if (GetWidget()) | 339 m_EdtEngine.SetAliasChar(wAlias); |
66 ToEdit(GetWidget())->SetAliasChar(wAlias); | 340 } |
| 341 |
| 342 bool CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_Edit::Undo() { |
| 401 if (!CanUndo()) |
| 402 return false; |
| 403 return Undo(m_DoRecords[m_iCurRecord--].get()); |
| 404 } |
| 405 |
| 406 bool CFWL_Edit::Redo() { |
| 407 if (!CanRedo()) |
| 408 return false; |
| 409 return Redo(m_DoRecords[++m_iCurRecord].get()); |
| 410 } |
| 411 |
| 412 bool CFWL_Edit::CanUndo() { |
| 413 return m_iCurRecord >= 0; |
| 414 } |
| 415 |
| 416 bool CFWL_Edit::CanRedo() { |
| 417 return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; |
| 418 } |
| 419 |
| 420 void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) { |
| 421 m_pOuter = pOuter; |
| 422 } |
| 423 |
| 424 void CFWL_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 CFWL_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 CFWL_Edit::On_SelChanged(CFDE_TxtEdtEngine* pEdit) { |
| 472 CFX_RectF rtTemp; |
| 473 GetClientRect(rtTemp); |
| 474 Repaint(&rtTemp); |
| 475 } |
| 476 |
| 477 bool CFWL_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 CFWL_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 CFWL_Edit::On_AddDoRecord(CFDE_TxtEdtEngine* pEdit, |
| 500 IFDE_TxtEdtDoRecord* pRecord) { |
| 501 AddDoRecord(pRecord); |
| 502 } |
| 503 |
| 504 bool CFWL_Edit::On_Validate(CFDE_TxtEdtEngine* pEdit, CFX_WideString& wsText) { |
| 505 CFWL_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; |
67 } | 516 } |
68 | 517 |
69 void CFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) { | 518 void CFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) { |
70 if (GetWidget()) | 519 m_fScrollOffsetY = fScrollOffset; |
71 ToEdit(GetWidget())->SetScrollOffset(fScrollOffset); | 520 } |
72 } | 521 |
| 522 void CFWL_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 CFWL_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 CFWL_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 CFWL_Edit::UpdateEditEngine() { |
| 663 UpdateEditParams(); |
| 664 UpdateEditLayout(); |
| 665 if (m_nLimit > -1) |
| 666 m_EdtEngine.SetLimit(m_nLimit); |
| 667 } |
| 668 |
| 669 void CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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* CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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(CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_Edit::ClearRecord() { |
| 1277 m_iCurRecord = -1; |
| 1278 m_DoRecords.clear(); |
| 1279 } |
| 1280 |
| 1281 void CFWL_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 CFWL_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 CFWL_Widget::OnProcessMessage(pMessage); |
| 1335 } |
| 1336 |
| 1337 void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) { |
| 1338 if (!pEvent) |
| 1339 return; |
| 1340 if (pEvent->GetClassID() != CFWL_EventType::Scroll) |
| 1341 return; |
| 1342 |
| 1343 CFWL_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 CFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics, |
| 1353 const CFX_Matrix* pMatrix) { |
| 1354 DrawWidget(pGraphics, pMatrix); |
| 1355 } |
| 1356 |
| 1357 void CFWL_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 CFWL_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 CFWL_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 CFWL_Edit::OnLButtonUp(CFWL_MsgMouse* pMsg) { |
| 1436 m_bLButtonDown = false; |
| 1437 SetGrab(false); |
| 1438 } |
| 1439 |
| 1440 void CFWL_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 CFWL_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 CFWL_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 CFWL_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 CFWL_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 |