mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-29 04:47:10 -06:00
- Model (doc::smart_art): layout, items (text + level), colour variant; capped at 100 items, 255 characters, 8 levels. - Layout algorithms of our own (docx::smart_art) place rounded rects, circles, bands, arrows and connectors; WordCraft draws the graphic from the same dsp:drawing it saves. - DOCX: data (dgm:dataModel points and connections), our own layout/quick-style/colour definitions under the built-in identifiers, the drawing part, relationships and content types. A diagram reads back editable only when its data part is exactly what WordCraft writes. - Commands: insert.smartArt, smartArt.items/addShape/promote/demote/layout/colors/reset/textPane, one undo step each; picture.size relays out a SmartArt graphic. - UI: layout picker with previews drawn in code, SmartArt Design tab, Text Pane; strings in all 9 catalogs. - Diagram reader draws `line` presets top-left to bottom-right (was the other diagonal). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
137 lines
4.8 KiB
Rust
137 lines
4.8 KiB
Rust
//! Charts and SmartArt diagrams: drawings kept as neutral items ready to draw. Charts and SmartArt
|
|
//! WordCraft can edit also keep their model ([`crate::chart::ChartSpec`],
|
|
//! [`crate::smart_art::SmartArtSpec`]); the rest are shown, not edited.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::para::ShapeKind;
|
|
use crate::props::Rgb;
|
|
|
|
/// A chart or a SmartArt diagram, as items ready to draw (and, for an editable chart or SmartArt
|
|
/// graphic, its model).
|
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Graphic {
|
|
pub kind: GraphicKind,
|
|
/// What to draw, in points from the object's top-left corner.
|
|
#[serde(default)]
|
|
pub items: Vec<GraphicItem>,
|
|
/// The size (points) the items were built for. Drawn scaled to the object's rectangle when
|
|
/// that differs (layout shrinks oversized inline objects); 0 means the rectangle's own size.
|
|
#[serde(default)]
|
|
pub w: f32,
|
|
#[serde(default)]
|
|
pub h: f32,
|
|
/// Where the graphic was read from, so saving writes the chart or diagram itself back (not
|
|
/// only these items). `None` for graphics made some other way.
|
|
#[serde(skip)]
|
|
pub source: Option<std::sync::Arc<Embedded>>,
|
|
/// A SmartArt graphic WordCraft can edit (one it made, or one read back exactly as it wrote
|
|
/// it): saving writes the diagram parts from it, and the items are drawn from it. See
|
|
/// [`crate::smart_art`].
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub smart_art: Option<std::sync::Arc<crate::smart_art::SmartArtSpec>>,
|
|
/// A chart WordCraft can edit (one it made, or one read back that holds nothing more): saving
|
|
/// writes the chart part from it, and the items are drawn from it. See [`crate::chart`].
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub chart: Option<std::sync::Arc<crate::chart::ChartSpec>>,
|
|
}
|
|
|
|
/// What an object read from a file needs to be written back as it was: its own markup in the
|
|
/// source format and the package parts that markup refers to. Never edited; WordCraft only moves
|
|
/// and resizes the object around it. The parts themselves (bytes, content type and their own
|
|
/// relationships) are kept in [`crate::Document::passthrough`] under their part names.
|
|
#[derive(Clone, Debug, Default, PartialEq)]
|
|
pub struct Embedded {
|
|
/// The object's markup as a standalone XML element with its namespace declarations (DOCX:
|
|
/// the `a:graphic` of a chart or SmartArt diagram, the `w:object` of an OLE object).
|
|
pub xml: String,
|
|
/// The relationships it uses, by the ids in `xml` (or in its parts, for a SmartArt drawing).
|
|
pub refs: Vec<EmbeddedRef>,
|
|
}
|
|
|
|
/// One relationship an [`Embedded`] object uses.
|
|
#[derive(Clone, Debug, Default, PartialEq)]
|
|
pub struct EmbeddedRef {
|
|
/// The relationship id the markup uses.
|
|
pub id: String,
|
|
/// Relationship type (a URI).
|
|
pub kind: String,
|
|
/// The part name (a `Document::passthrough` key), or the URL of an external target.
|
|
pub target: String,
|
|
pub external: bool,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub enum GraphicKind {
|
|
#[default]
|
|
Chart,
|
|
Diagram,
|
|
}
|
|
|
|
impl GraphicKind {
|
|
/// What the graphic is, in words: the alt text of one that has none of its own.
|
|
pub fn noun(self) -> &'static str {
|
|
match self {
|
|
GraphicKind::Chart => "chart",
|
|
GraphicKind::Diagram => "diagram",
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "camelCase")]
|
|
pub enum GraphicItem {
|
|
/// A preset shape filling `rect` ([x, y, w, h]).
|
|
Shape {
|
|
rect: [f32; 4],
|
|
kind: ShapeKind,
|
|
fill: Option<Rgb>,
|
|
stroke: Option<Rgb>,
|
|
#[serde(default)]
|
|
stroke_width: f32,
|
|
},
|
|
/// A path: polygons, pie slices, line series.
|
|
Path {
|
|
segs: Vec<PathSeg>,
|
|
fill: Option<Rgb>,
|
|
stroke: Option<Rgb>,
|
|
#[serde(default)]
|
|
stroke_width: f32,
|
|
},
|
|
/// One line of text in `rect`, aligned horizontally by `align`, centred vertically.
|
|
Text {
|
|
rect: [f32; 4],
|
|
text: String,
|
|
size: f32,
|
|
color: Rgb,
|
|
#[serde(default)]
|
|
bold: bool,
|
|
#[serde(default)]
|
|
align: TextAlign,
|
|
#[serde(default)]
|
|
font: Option<String>,
|
|
},
|
|
/// A picture (`Document::media` key) stretched into `rect`.
|
|
Image { rect: [f32; 4], media: String },
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub enum TextAlign {
|
|
Left,
|
|
#[default]
|
|
Center,
|
|
Right,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub enum PathSeg {
|
|
Move(f32, f32),
|
|
Line(f32, f32),
|
|
Cubic(f32, f32, f32, f32, f32, f32),
|
|
Close,
|
|
}
|