Pure Codename One rich text and code editors (remove BrowserComponent)#5378
Conversation
Replace the BrowserComponent-backed RichTextArea and CodeEditor with a 100% pure Codename One text engine (com.codename1.ui.editor) that renders the document itself with Graphics/Font and binds to the platform text input source. - New low-level text input source API (TextInputClient/State/Config + impl SPI) bound per port: Android custom InputConnection, iOS UITextInput first responder, JavaSE InputMethod/key listeners. - Editor engine: document model, incremental stateful tokenizer, undo, styled rich runs, HTML import/export, code completion popup and diagnostics squiggles. - Bidirectional (RTL) text via a Unicode Bidi Algorithm core (BidiUtil) wired into caret/selection/hit-test/render for the base, code and rich views. - IME / CJK marked-text composition with an inline underline. - Native-feel touch selection: cross-platform CN1-drawn handles + magnifier loupe + Copy/Cut/Paste/Select All, plus the native iOS system magnifier / handles / edit menu via UITextInteraction. - Remove the HTML/BrowserComponent backend (CodeEditorHtml, createEditorHtml) and the dead CodeEditor CodeMirror bundling in the Maven plugin builders and GLViewController.h. Public API preserved (drop-in); backend-switch methods kept as deprecated no-ops. - Tests: 66 core unit tests (bidi, document, composing, geometry, backend) plus a hellocodenameone screenshot test. Full core-unittests suite green (3867). - Developer guide updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Compared 12 screenshots: 12 matched. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
|
Compared 146 screenshots: 146 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
Cloudflare Preview
|
|
Compared 142 screenshots: 142 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 169 screenshots: 169 matched. |
|
Compared 143 screenshots: 143 matched. |
|
Compared 143 screenshots: 143 matched. |
|
Compared 144 screenshots: 144 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 217 screenshots: 217 matched. |
|
Compared 139 screenshots: 139 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 140 screenshots: 140 matched. |
|
Compared 145 screenshots: 145 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
The core-unittests SpotBugs check (threshold Low, fail on any) flagged the new editor code. Fix the real findings and suppress a style-only one: - BidiUtil: use a bitwise odd-check (IM_BAD_CHECK_FOR_ODD) and drop the unreachable 0x00A0 branch in typeOf (UC_USELESS_CONDITION). - RichPureEditor.loadImage: avoid String.getBytes() default encoding (DM_DEFAULT_ENCODING) by converting the ASCII base64 payload directly, and use >= 0 for the indexOf checks (RV_CHECK_FOR_POSITIVE_INDEXOF). - RichView.setList: remove a dead local store (DLS_DEAD_LOCAL_STORE). - spotbugs-exclude: suppress SIC_INNER_SHOULD_BE_STATIC_ANON for the editor package (its StyleTransform/StylePredicate/BlockOp anonymous impls capture only locals; the refactor is noise). Also add EditorLayoutTest verifying RichTextArea/CodeEditor lay out below the form Toolbar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HtmlImporter only handled amp/lt/gt/quot/apos/nbsp and numeric entities, so common named entities such as — rendered as literal text. Add the common typography and symbol entities (mdash, ndash, hellip, curly quotes, copy, reg, trade, times, euro, pound, ...). Covered by HtmlImporterTest. Also add getVerticalScroll() plus EditorFirstLineTest, which confirms the editor shows line 0 at the top after loading content (scroll stays 0), complementing EditorLayoutTest (editors sit below the form Toolbar). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
setText() reset scrollY to 0 and then called scrollCaretVisible(). When the backend flushes the queued setText before the component is laid out (getHeight() is still 0), contentHeight() is negative once padding is subtracted, so the "caret below the viewport" branch fired even for the caret on line 0 and pushed scrollY to roughly one line. The first content line then scrolled under the form title bar on device and in the simulator (headless tests missed it because they set the text after layout). Guard scrollCaretVisible() against an unlaid-out viewport (contentHeight <= 0) and add a laidOut() override that re-clamps scrollY and applies any deferred scroll-to-caret once the real bounds are known. Add a regression test that sets the text before the first layout, reproducing the device ordering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pure editor code tripped several CI gates that only run in the full PR workflow (not the SpotBugs-only local check): - PMD forbidden-rules gate (generate-quality-report.py): resolved 62 findings in the new editor sources - add @OverRide where methods override/implement, convert indexed loops to foreach, split multi-declarations, drop unnecessary fully-qualified names / imports / constructor, make BidiUtil final, remove unused measureLine params, and restructure a break-as-last-in-loop into a helper. Genuine identity comparisons (cached fonts, the ThemePalette singleton) and owned StringBuilder buffers (document buffer, HTML importer) are marked // NOPMD with a reason since changing them would be incorrect. - JavaDoc package-info gate: add package-info.java for com.codename1.ui.editor. - Developer guide quality gate: fix the Vale findings in the RichTextArea / CodeEditor sections (contraction, cliche, adverb) and disable the LanguageTool UPPERCASE_SENTENCE_START rule, which false-positives on deliberately lowercase asciidoc ordered-list continuation items (matching the existing ENGLISH_WORD_REPEAT_BEGINNING_RULE exception). No behavior change. Verified: core-unittests verify (3876 tests pass, SpotBugs 0 bugs, PMD gate clean), Vale 0/0/0 on the edited guide, package-info check passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The RichTextArea and CodeEditor screenshot tests pre-date this PR and their goldens were captured against the old BrowserComponent editor; the new PureEditors test had none. Re-capture all three from the CI run of the fixed commit (first line no longer clipped, HTML entities and RTL/bidi rendering correctly) across every capturing platform (android, javascript, windows, mac-native, linux x64/arm, iOS gl/metal/tv/watch). Refresh the tolerance comments to describe the pure text render instead of the removed web widget. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
PureEditorScreenshotTest was registered before the graphics screenshot tests. Creating a pure editor warms Android's native-font path, so the default-font text drawn by graphics-draw-string, graphics-draw-string-decorated and graphics-inscribed-triangle-grid rendered differently than their goldens (which were captured with the editor tests running after the graphics suite, like RichTextArea/CodeEditor already do). Android-only, deterministic since the first branch commit; other platforms were unaffected. Move the test into the editor-screenshot cluster so every editor test runs after the graphics tests, restoring the cold-font ordering the graphics goldens capture. No production code change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 142 screenshots: 142 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 142 screenshots: 142 matched. Benchmark ResultsDetailed Performance Metrics
|
Blog prose gate✅ No net-new prose findings introduced by this PR. |
Summary
Replaces the
BrowserComponent-backedRichTextArea(WYSIWYG) andCodeEditorwith a 100% pure Codename One text engine (com.codename1.ui.editor) that renders the document itself withGraphics/Fontand binds directly to the platform text input source (soft keyboard, hardware/Bluetooth keyboard, IME). The public API of both components is preserved, so this is a drop-in replacement.What's included
TextInputClient/TextInputState/TextInputConfig+ an impl SPI onCodenameOneImplementation), bound per port:InputConnection(CN1TextInputConnection) on the surface views (no shadowEditText).UITextInputview (CN1TextInputView) - soft + hardware/Bluetooth keyboard + IME.InputMethodListener+ key listeners.BidiUtil) wired into caret geometry, hit-testing, selection and rendering for the base, code and rich views (mixed LTR/RTL, numbers-in-RTL, etc.).UITextInteraction(verified on device).CodeEditorHtmland thecreateEditorHtml()paths, and the now-dead CodeEditor -> CodeMirror bundling in the Maven pluginIPhoneBuilder/AndroidGradleBuilderandGLViewController.h. Backend-switch methods (setDefaultBackend,getInternalBrowser,CodeEditor.setEngineURL, ...) are kept as deprecated no-ops for source compatibility.Testing
com.codename1.ui.editor.*): bidi algorithm + geometry integration, document model, CJK composing, pure-backend selection/round-trip.core-unittestssuite green: 3867 tests, 0 failures.PureEditorScreenshotTest(RTL-in-code + mixed rich text) added to the hellocodenameone suite; itsPureEditorsgolden adopts from the first CI run.Notes
drop-codemirror-editor).Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
🤖 Generated with Claude Code