Text-Erstellung mit Floating-Input-Box (Variante B)
Neuer Workflow: Klick "+ Text" in Topbar → Punkt im Viewport picken → Floating Eto-Dialog erscheint neben dem Mauszeiger → User tippt → Enter fuegt TextEntity mit Topbar-Settings ein. Esc bricht ab. Backend (rhino/text_create.py): - load_settings/save_settings — persistiert font/size/bold/italic in doc.Strings["dossier_text_settings"] (JSON) - available_fonts() — System-Font-Namen via Rhino.DocObjects.Font.AvailableFontFaceNames - _floating_input() — Eto.Dialog mit TextBox, ShowModal mit Rhino- MainWindow als Parent, positioniert bei Mouse.Position - create_text() — RhinoGet.GetPoint → _floating_input → TextEntity mit Font/Size/Bold/Italic erstellen + AddText - _apply_font() mit 2 Fallback-Pfaden (FontTable.FindOrCreate + Font.FromQuartetProperties) fuer RhinoCommon-Kompatibilitaet Backend (oberleiste.py): - CREATE_TEXT handler → text_create.create_text() - SET_TEXT_SETTINGS handler → text_create.save_settings (merge partial) - State payload: textSettings (immer) + textFonts (einmalig initial, via _fonts_sent Flag — Liste aendert sich nicht zur Laufzeit) Frontend (OberleisteApp + rhinoBridge): - createText() + setTextSettings() Bridge-Funktionen - Text-Block 2x2 Grid analog Massstab: R1: Font-Dropdown (BarCombo mit text_fields icon) | Size-Input mit "m" suffix R2: B/I-Toggles (segmented pill mit accent-Fill bei active) | "+ Text" Button - Hover-Logik analog View-Toggle (bg → bg-item-hover, color → accent-light) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+143
-1
@@ -11,7 +11,7 @@ import {
|
||||
deleteLayerCombination, openLayerCombinationsDialog,
|
||||
openDossierSettings, openKameraPanel,
|
||||
setMasseActive, openMasseSettings,
|
||||
openAbout,
|
||||
openAbout, createText, setTextSettings,
|
||||
} from './lib/rhinoBridge'
|
||||
|
||||
const PRESETS = [
|
||||
@@ -305,6 +305,8 @@ export default function OberleisteApp() {
|
||||
overridesActivePreset: null, overridesPresets: [],
|
||||
layerCombinations: [], layerCombinationActive: null,
|
||||
massePresets: [], masseActiveId: null,
|
||||
textSettings: { font: 'Helvetica', size: 0.20, bold: false, italic: false },
|
||||
textFonts: [],
|
||||
})
|
||||
const [appliedScale, setAppliedScale] = useState(null)
|
||||
const appliedScaleRef = useRef(null)
|
||||
@@ -759,6 +761,146 @@ export default function OberleisteApp() {
|
||||
)
|
||||
})()}
|
||||
|
||||
<div style={sep} />
|
||||
|
||||
{/* ====== TEXT-Block 2-Reihen ======
|
||||
Reihe 1: Font-Dropdown + Groesse (mm)
|
||||
Reihe 2: B/I-Toggles + "Text einfuegen"-Button
|
||||
*/}
|
||||
{(() => {
|
||||
const ts = state.textSettings || {}
|
||||
const fonts = state.textFonts || []
|
||||
const updateTs = (patch) => setTextSettings({ ...ts, ...patch })
|
||||
const TEXT_W = 150
|
||||
return (
|
||||
<div style={{
|
||||
display: 'grid', gridTemplateColumns: 'auto auto', gap: '4px 6px',
|
||||
alignItems: 'center', flexShrink: 0,
|
||||
}}>
|
||||
{/* Reihe 1, Spalte 1: Font-Dropdown */}
|
||||
<BarCombo
|
||||
icon="text_fields"
|
||||
value={ts.font || ''}
|
||||
onChange={(v) => updateTs({ font: v })}
|
||||
width={TEXT_W}
|
||||
title="Schriftart"
|
||||
>
|
||||
{fonts.length === 0 && <option value="">—</option>}
|
||||
{fonts.map(f => <option key={f} value={f}>{f}</option>)}
|
||||
</BarCombo>
|
||||
{/* Reihe 1, Spalte 2: Groesse (mm) */}
|
||||
<div style={{
|
||||
display: 'inline-flex', alignItems: 'center', gap: 4,
|
||||
height: BAR_H, padding: '0 10px',
|
||||
background: 'var(--bg-input)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 999,
|
||||
flexShrink: 0, width: 90,
|
||||
}}>
|
||||
<input
|
||||
type="number" step="0.01" min="0.01"
|
||||
value={ts.size != null ? ts.size : 0.2}
|
||||
onChange={(e) => {
|
||||
const v = parseFloat(e.target.value)
|
||||
if (!isNaN(v) && v > 0) updateTs({ size: v })
|
||||
}}
|
||||
style={{
|
||||
flex: 1, minWidth: 0,
|
||||
background: 'transparent', border: 'none', outline: 'none',
|
||||
color: 'var(--text-primary)',
|
||||
fontSize: 11, fontFamily: 'DM Mono, monospace',
|
||||
padding: 0, textAlign: 'right',
|
||||
appearance: 'auto',
|
||||
}}
|
||||
title="Texthoehe in Model-Units"
|
||||
/>
|
||||
<span style={{ fontSize: 9, color: 'var(--text-muted)' }}>m</span>
|
||||
</div>
|
||||
{/* Reihe 2, Spalte 1: B/I-Toggles */}
|
||||
<div style={{
|
||||
display: 'inline-flex',
|
||||
border: '1px solid var(--border)', borderRadius: 999,
|
||||
overflow: 'hidden', flexShrink: 0, width: TEXT_W,
|
||||
}}>
|
||||
<button
|
||||
onClick={() => updateTs({ bold: !ts.bold })}
|
||||
onMouseEnter={(e) => {
|
||||
if (ts.bold) return
|
||||
e.currentTarget.style.background = 'var(--bg-item-hover)'
|
||||
e.currentTarget.style.color = 'var(--accent-light)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (ts.bold) return
|
||||
e.currentTarget.style.background = 'var(--bg-input)'
|
||||
e.currentTarget.style.color = 'var(--text-primary)'
|
||||
}}
|
||||
style={{
|
||||
flex: 1, height: BAR_H,
|
||||
background: ts.bold ? 'var(--accent)' : 'var(--bg-input)',
|
||||
color: ts.bold ? 'var(--bg-panel)' : 'var(--text-primary)',
|
||||
border: 'none', cursor: 'pointer',
|
||||
fontWeight: 700, fontSize: 11,
|
||||
transition: 'background 0.15s, color 0.15s',
|
||||
}}
|
||||
title="Fett"
|
||||
>B</button>
|
||||
<button
|
||||
onClick={() => updateTs({ italic: !ts.italic })}
|
||||
onMouseEnter={(e) => {
|
||||
if (ts.italic) return
|
||||
e.currentTarget.style.background = 'var(--bg-item-hover)'
|
||||
e.currentTarget.style.color = 'var(--accent-light)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (ts.italic) return
|
||||
e.currentTarget.style.background = 'var(--bg-input)'
|
||||
e.currentTarget.style.color = 'var(--text-primary)'
|
||||
}}
|
||||
style={{
|
||||
flex: 1, height: BAR_H,
|
||||
background: ts.italic ? 'var(--accent)' : 'var(--bg-input)',
|
||||
color: ts.italic ? 'var(--bg-panel)' : 'var(--text-primary)',
|
||||
border: 'none', borderLeft: '1px solid var(--border)',
|
||||
cursor: 'pointer',
|
||||
fontStyle: 'italic', fontSize: 11,
|
||||
transition: 'background 0.15s, color 0.15s',
|
||||
}}
|
||||
title="Kursiv"
|
||||
>I</button>
|
||||
</div>
|
||||
{/* Reihe 2, Spalte 2: "Text einfuegen" Button */}
|
||||
<button
|
||||
onClick={() => createText()}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = 'var(--bg-item-hover)'
|
||||
e.currentTarget.style.borderColor = 'var(--accent)'
|
||||
e.currentTarget.style.color = 'var(--accent-light)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = 'var(--bg-input)'
|
||||
e.currentTarget.style.borderColor = 'var(--border)'
|
||||
e.currentTarget.style.color = 'var(--text-primary)'
|
||||
}}
|
||||
style={{
|
||||
width: 90, height: BAR_H,
|
||||
background: 'var(--bg-input)',
|
||||
color: 'var(--text-primary)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 999,
|
||||
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
||||
gap: 4, cursor: 'pointer',
|
||||
fontSize: 11, fontWeight: 500,
|
||||
transition: 'background 0.15s, color 0.15s, border-color 0.15s',
|
||||
}}
|
||||
title="Position picken → Text tippen → Enter"
|
||||
>
|
||||
<Icon name="add" size={12} />
|
||||
Text
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Snap-Toggles (Ortho/Grid/OSnap) sind in Rhinos eigener Footer-Bar
|
||||
schon vorhanden — hier rausgenommen um Doppelung zu vermeiden. */}
|
||||
|
||||
|
||||
@@ -171,6 +171,8 @@ export function saveOverridesPreset(name) { send('SAVE_OVERRIDES_PRESET', { name
|
||||
export function openOverridesPanel() { send('OPEN_OVERRIDES_PANEL', {}) }
|
||||
export function openKameraPanel() { send('OPEN_KAMERA_PANEL', {}) }
|
||||
export function openAbout() { send('OPEN_ABOUT', {}) }
|
||||
export function createText() { send('CREATE_TEXT', {}) }
|
||||
export function setTextSettings(settings) { send('SET_TEXT_SETTINGS', { settings }) }
|
||||
|
||||
// --- Masse (in Oberleiste + Satellite-Fenster MasseSettings) ---
|
||||
// Topbar: aktives Mass setzen + Settings-Fenster oeffnen
|
||||
|
||||
Reference in New Issue
Block a user