Doppelklick-Hook auf DOSSIER-Texte + Size-Mapping in RTF
User: Doppelklick auf DOSSIER-Text oeffnet weiterhin Rhinos Editor. Verschiedene Groessen im Editor erscheinen nicht in Rhino. Doppelklick-Hook (rhino/text_editor.py): - _DossierTextDoubleClickHook subklassiert Rhino.UI.MouseCallback. OnMouseDoubleClick prueft selektierte TextEntities auf UserString "dossier_text"="1" und cancelled das Event (= blockt Rhinos Standard-TextEdit-Dialog), setzt sticky["dossier_pending_text_edit"] mit der Obj-ID - _on_idle_check_pending_edit (RhinoApp.Idle event): nimmt sticky-ID auf naechstem Idle-Tick und ruft open_for_edit(obj) — defer noetig weil Eto-Form aus MouseCallback heraus oeffnen Re-Entrancy macht - _ensure_double_click_hook() installiert Hook + Idle-Handler einmalig pro Rhino-Session (idempotent) - startup.py ruft das jetzt direkt nach Modul-Load auf Edit-Mode (open_for_edit): - Liest aus bestehendem TextEntity die Settings (Font, Size, Bold, Italic, Underline, Align) + PlainText - Frame fuer Dialog-Positionierung aus BBox abgeleitet - TextEditorBridge mit edit_obj_id + initial_text gestartet - INIT-Payload um initialText + editMode erweitert - COMMIT: bei edit_obj_id gesetzt → doc.Objects.Replace statt AddText. Plane wird vom Original uebernommen wenn keine explizite Rotation, damit der Text an seinem Platz bleibt Frontend (TextEditorApp.jsx): - Bei INIT mit initialText: editor.innerText wird damit befuellt - htmlToRuns extrahiert font-size in Pixel pro Run (inline style oder computed style != base) - baseCtx _basePx aus computed style des Editor-divs Size-Mapping (rhino/text_editor.py _runs_to_rtf): - fontSizePx in Runs triggert non-trivial (RTF wird generiert) - Pro Run: \fs in Halb-Punkten = 20 * (run_px / 14_base_px) round - 14px = \fs20 (1.0× TextEntity.TextHeight) - 21px = \fs30 (1.5×) - 28px = \fs40 (2.0×) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+21
-6
@@ -108,9 +108,6 @@ function htmlToRuns(rootEl) {
|
||||
// Computed style oder inline style.
|
||||
const cs = window.getComputedStyle ? window.getComputedStyle(node) : null
|
||||
if (node.style.fontFamily) nc.font = node.style.fontFamily.replace(/['"]/g, '').split(',')[0].trim()
|
||||
else if (cs?.fontFamily && cs.fontFamily !== ctx.font && cs.fontFamily) {
|
||||
// nur uebernehmen wenn explizit anders
|
||||
}
|
||||
if (node.style.color) nc.color = node.style.color
|
||||
if (node.style.fontWeight) {
|
||||
const fw = node.style.fontWeight
|
||||
@@ -118,6 +115,14 @@ function htmlToRuns(rootEl) {
|
||||
}
|
||||
if (node.style.fontStyle === 'italic') nc.italic = true
|
||||
if (node.style.textDecoration?.includes('underline')) nc.underline = true
|
||||
// Font-Size: aus inline-style oder computed style (Pixel)
|
||||
if (node.style.fontSize) {
|
||||
const m = node.style.fontSize.match(/(\d+\.?\d*)px/)
|
||||
if (m) nc.fontSizePx = parseFloat(m[1])
|
||||
} else if (cs?.fontSize) {
|
||||
const px = parseFloat(cs.fontSize)
|
||||
if (px && px !== ctx._basePx) nc.fontSizePx = px
|
||||
}
|
||||
// Legacy <font> Element von execCommand
|
||||
if (tag === 'font') {
|
||||
const c = node.getAttribute('color'); if (c) nc.color = c
|
||||
@@ -130,8 +135,10 @@ function htmlToRuns(rootEl) {
|
||||
flush('\n', ctx)
|
||||
}
|
||||
}
|
||||
const basePx = parseFloat(window.getComputedStyle(rootEl).fontSize) || 14
|
||||
const baseCtx = { font: null, color: null, bold: false, italic: false,
|
||||
underline: false, sup: false, sub: false }
|
||||
underline: false, sup: false, sub: false,
|
||||
fontSizePx: null, _basePx: basePx }
|
||||
for (const child of rootEl.childNodes) walk(child, baseCtx)
|
||||
// Trailing-Newline weg
|
||||
if (runs.length && runs[runs.length-1].text === '\n') runs.pop()
|
||||
@@ -221,8 +228,16 @@ export default function TextEditorApp() {
|
||||
if (s.italic != null) setItalic(!!s.italic)
|
||||
if (s.underline != null) setUnderline(!!s.underline)
|
||||
if (s.align) setAlign(s.align)
|
||||
// Editor-Default-Font setzen
|
||||
setTimeout(() => editorRef.current?.focus(), 100)
|
||||
// Bei Edit-Mode: bestehenden Text in den Editor laden
|
||||
const initialText = data.initialText || ''
|
||||
setTimeout(() => {
|
||||
if (editorRef.current) {
|
||||
if (initialText) {
|
||||
editorRef.current.innerText = initialText
|
||||
}
|
||||
editorRef.current.focus()
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
notifyReady()
|
||||
}, [])
|
||||
|
||||
Reference in New Issue
Block a user