Module: Ea::Svg::EaEmitter::Compartment::NoteText
- Defined in:
- lib/ea/svg/ea_emitter/compartment/note_text.rb
Overview
Note text compartment. When diagram.show_notes is true, renders the classifier's documentation note (from t_object.Note) as wrapped text lines in the element body. Lines are estimated by character width and split at word boundaries to fit the element bounds.
Constant Summary collapse
- X_PADDING =
5- Y_FIRST_OFFSET =
15- LINE_OFFSET =
13- CHAR_WIDTH_FACTOR =
0.55
Class Method Summary collapse
- .build_text(content, x_pos, y_pos, context, fill) ⇒ Object
- .note_bodies(classifier) ⇒ Object
- .render(context) ⇒ Object
- .show_notes?(context) ⇒ Object
- .wrap_group(body, fill) ⇒ Object
-
.wrapped_lines(text, max_chars) ⇒ Object
Word-wrap text at max_chars, preserving word boundaries.
Class Method Details
.build_text(content, x_pos, y_pos, context, fill) ⇒ Object
79 80 81 82 83 84 85 86 87 |
# File 'lib/ea/svg/ea_emitter/compartment/note_text.rb', line 79 def build_text(content, x_pos, y_pos, context, fill) TextRenderer.new( content: content, x: x_pos, y: y_pos, family: context.family, size: context.size, size_unit: context.size_unit, fill: fill, style: "italic" ).to_svg end |
.note_bodies(classifier) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/ea/svg/ea_emitter/compartment/note_text.rb', line 49 def note_bodies(classifier) (classifier.annotations || []).filter_map do |a| body = a.body.to_s.strip body.empty? ? nil : body end end |
.render(context) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/ea/svg/ea_emitter/compartment/note_text.rb', line 20 def render(context) return nil unless show_notes?(context) return nil unless context.classifier&.is_a?(Ea::Model::Classifier) notes = note_bodies(context.classifier) return nil if notes.empty? first_y = context.geometry.attr_first_y + Y_FIRST_OFFSET bounds = context.bounds fill = context.theme.attribute_text_color usable_width = bounds.width - (X_PADDING * 2) max_chars = (usable_width / (context.size * CHAR_WIDTH_FACTOR)).floor texts = [] y = first_y notes.each do |body| wrapped_lines(body, max_chars).each do |line| texts << build_text(line, bounds.x + X_PADDING, y, context, fill) y += LINE_OFFSET end end wrap_group(texts.join("\n"), fill) end |
.show_notes?(context) ⇒ Object
44 45 46 |
# File 'lib/ea/svg/ea_emitter/compartment/note_text.rb', line 44 def show_notes?(context) context.diagram && context.diagram.show_notes end |
.wrap_group(body, fill) ⇒ Object
90 91 92 93 94 95 96 |
# File 'lib/ea/svg/ea_emitter/compartment/note_text.rb', line 90 def wrap_group(body, fill) style = "stroke-width:1;stroke-linecap:round;" \ "stroke-linejoin:bevel; fill:#{fill};" \ "fill-opacity:1.00; stroke:#000000;" \ " stroke-opacity:0.00" %(<g style="#{style}">\n#{body}\n</g>) end |
.wrapped_lines(text, max_chars) ⇒ Object
Word-wrap text at max_chars, preserving word boundaries.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/ea/svg/ea_emitter/compartment/note_text.rb', line 58 def wrapped_lines(text, max_chars) return [text] if text.length <= max_chars words = text.split(" ") lines = [] current = "" words.each do |word| if current.empty? current = word elsif (current + " " + word).length <= max_chars current = "#{current} #{word}" else lines << current current = word end end lines << current unless current.empty? lines end |