Automatically introducing \n (newlines) after some designated character count.

as discussed: https://community.osarch.org/discussion/2485/automatically-introducing-n-newlines-after-some-designated-character-count
This commit is contained in:
Ryan Schultz
2024-11-17 17:08:10 -06:00
parent bc2f6b61e0
commit 812e3dc6df
8 changed files with 69 additions and 5 deletions
@@ -1,11 +1,11 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION((),'2;1');
FILE_NAME('Psets_BBIM_Annotation.ifc','2020-01-01T00:00:00',(),(),'Psets_BBIM_Annotation','Psets_BBIM_Annotation',$);
FILE_DESCRIPTION($,'2;1');
FILE_NAME('Psets_BBIM_Annotation.ifc','2020-01-01T00:00:00',$,$,'Psets_BBIM_Annotation','Psets_BBIM_Annotation',$);
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation,IfcTypeProduct',(#2,#3,#4));
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation,IfcTypeProduct',(#2,#3,#4,#29));
#2=IFCSIMPLEPROPERTYTEMPLATE('2P7JN79n96Q9pElZ83LKe4',$,'ZIndex','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
#3=IFCSIMPLEPROPERTYTEMPLATE('1Wpx_r2xj1_9w5JpI0QRJy',$,'Symbol','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
#4=IFCSIMPLEPROPERTYTEMPLATE('3q0oxMUKP47vZ4jnyG$dDb',$,'Classes','Classes separarated by spaces that end up in classes for this element in svg. Can be used to specify the text font size: small - 1.8mm; regular - 2.5mm; large - 3.5mm; header - 5mm; title - 7mm. By default regular size is used.',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
@@ -33,6 +33,6 @@ DATA;
#26=IFCSIMPLEPROPERTYTEMPLATE('0SVyOfB0rC2xNfdRYf3XvY',$,'SuppressZeroInches','Suppress 0 inch values in dimension annotation text (for example: 12'' - 0" -> 12'')',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#27=IFCSIMPLEPROPERTYTEMPLATE('2bUmj458PBqPAtUoI3MXsb',$,'TextPrefix','Text to add before annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
#28=IFCSIMPLEPROPERTYTEMPLATE('0bnzttUb9BPuN597uNTXOE',$,'TextSuffix','Text to add after annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
#29=IFCSIMPLEPROPERTYTEMPLATE('2pJmUDpB50VBdCOib1zcJJ',$,'Newline_At','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
ENDSEC;
END-ISO-10303-21;
@@ -605,8 +605,16 @@ class BaseDecorator:
font_size_mm = text_data["FontSize"] * text_scale
for literal_data in literals_data:
box_alignment = literal_data["BoxAlignment"]
text = literal_data["CurrentValue"]
for line in literal_data["CurrentValue"].split("\n"):
newline_at = props.newline_at
if newline_at != 0:
text = helper.add_newline_between_words (text, newline_at)
multiple_lines = text.split("\n")
for line in multiple_lines:
self.draw_label(
context,
line,
@@ -622,6 +630,8 @@ class BaseDecorator:
line_i += 1 if not reverse_lines_order else -1
class DimensionDecorator(BaseDecorator):
"""Decorator for dimension objects
- each edge of a segment with arrow
@@ -414,3 +414,30 @@ def elevate_segment(bounds, segm):
return None
x = p1.x
return [Vector((x, ymin, zmin)), Vector((x, ymax, zmin))]
def add_newline_between_words(text, newline_at):
result = []
start = 0
while start < len(text):
# Find the end index considering the limit newline_at
end = start + newline_at
if end >= len(text): # If we're at the end of the string
result.append(text[start:])
break
# Look for the nearest space around the newline_at limit
space_index = text.rfind(' ', start, end) # Try to break before newline_at
if space_index == -1: # No space found, force a break at newline_at
space_index = text.find(' ', end) # Try to break after newline_at
if space_index == -1: # If there's still no space, take the rest of the text
result.append(text[start:])
break
# Add the chunk and update the start position
result.append(text[start:space_index])
start = space_index + 1 # Skip the space itself
return '\n'.join(result)
@@ -522,6 +522,7 @@ class BIMTextProperties(PropertyGroup):
default="2.5",
name="Font Size",
)
newline_at: IntProperty(name="Newline At")
def get_text_edited_data(self):
"""should be called only if `is_editing`
@@ -841,6 +841,7 @@ class SvgWriter:
self.draw_symbol(symbol, symbol_transform)
line_number = 0
newline_at = text_obj.BIMTextProperties.newline_at
for text_literal in text_literals:
text = tool.Drawing.replace_text_literal_variables(text_literal.Literal, product or element)
text_tags = self.create_text_tag(
@@ -851,6 +852,7 @@ class SvgWriter:
classes_str,
fill_bg=fill_bg,
line_number_start=line_number,
newline_at = newline_at,
)
for tag in text_tags:
self.svg.add(tag)
@@ -1373,6 +1375,7 @@ class SvgWriter:
multiline_to_bottom=True,
fill_bg=False,
line_number_start=0,
newline_at=0,
):
"""returns list of created text tags"""
text_tags = []
@@ -1402,6 +1405,8 @@ class SvgWriter:
text_tag = self.svg.text("", **text_kwargs, **base_text_attrs)
text_tags.append(text_tag)
if newline_at != 0:
text = helper.add_newline_between_words (text, newline_at)
text_lines = text.replace("\\n", "\n").split("\n")
text_lines = text_lines if multiline_to_bottom else text_lines[::-1]
@@ -533,6 +533,8 @@ class BIM_PT_text(Panel):
row = self.layout.row(align=True)
row.prop(props, "font_size")
row = self.layout.row(align=True)
row.prop(props, "newline_at")
for i, literal_props in enumerate(props.literals):
box = self.layout.box()
@@ -574,6 +576,9 @@ class BIM_PT_text(Panel):
row = self.layout.row(align=True)
row.label(text="FontSize")
row.label(text=str(text_data["FontSize"]))
row = self.layout.row(align=True)
row.label(text="Newline_At")
row.label(text=str(props.newline_at))
for literal_data in text_data["Literals"]:
box = self.layout.box()
+1
View File
@@ -39,6 +39,7 @@ def disable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
def edit_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.synchronise_ifc_and_text_attributes(obj)
drawing.update_text_size_pset(obj)
drawing.update_newline_at(obj)
drawing.update_text_value(obj)
drawing.disable_editing_text(obj)
+15
View File
@@ -1021,6 +1021,21 @@ class Drawing(bonsai.core.tool.Drawing):
properties={"Classes": classes},
)
@classmethod
def update_newline_at(cls, obj: bpy.types.Object) -> None:
props = obj.BIMTextProperties
element = tool.Ifc.get_entity(obj)
newline_at = int(props.newline_at)
ifc_file = tool.Ifc.get()
pset = tool.Pset.get_element_pset(element, "EPset_Annotation")
if not pset:
pset = ifcopenshell.api.run("pset.add_pset", ifc_file, product=element, name="EPset_Annotation")
ifcopenshell.api.run(
"pset.edit_pset",
ifc_file,
pset=pset,
properties={"Newline_At": newline_at},
)
# TODO below this point is highly experimental prototype code with no tests
@classmethod