#!/usr/bin/env python3 """Folie 4 – Eventstream als Quelle; Aussagen links, Lupen rechts, Strecke unten (adesso-Styling).""" import os from pptx import Presentation from pptx.util import Inches, Pt from pptx.dml.color import RGBColor from pptx.enum.text import PP_ALIGN, MSO_ANCHOR from pptx.enum.shapes import MSO_SHAPE from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, RECF, F, FC, paint_background, chrome) # Rollen-Mapping auf die adesso-Palette NAVY = INK # dunkle Füllungen (Lupe, Maschine) ACCENT = CORAL AMBER = GREEN GLASS = RECF BELT = RECF DARK = INK LINEC = LIGHT THIN = LIGHT STREAM = INK MID = RGBColor(0x34, 0x4E, 0x70) prs = Presentation() prs.slide_width = Inches(13.333) prs.slide_height = Inches(7.5) SW, SH = prs.slide_width, prs.slide_height s = prs.slides.add_slide(prs.slide_layouts[6]) def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0): sh = s.shapes.add_shape(kind, x, y, w, h) if fill is None: sh.fill.background() else: sh.fill.solid(); sh.fill.fore_color.rgb = fill if line is None: sh.line.fill.background() else: sh.line.color.rgb = line; sh.line.width = lw if rot: sh.rotation = rot sh.shadow.inherit = False return sh def txt(x, y, w, h, t, size=16, color=WHITE, bold=False, italic=False, align=PP_ALIGN.LEFT, spc=None, font=F): tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0) p = tf.paragraphs[0]; p.alignment = align r = p.add_run(); r.text = t r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic r.font.name = font; r.font.color.rgb = color if spc: r.font._rPr.set('spc', str(spc)) return tb paint_background(s, SW, SH) chrome(s, "Zustand oder Ereignis", 5) x0, x1 = Inches(1.0), Inches(12.33) beltw = x1 - x0 # ---- Aussagen links -------------------------------------------------------- claims = [ "Eventstream = einzige Quelle der Wahrheit", "kann nicht überschrieben werden", "vollständige 3D-Sicht auf Maschine / Strang", ] cy = Inches(1.95) for i, c in enumerate(claims): y = cy + Inches(0.6) * i shp(MSO_SHAPE.RECTANGLE, Inches(0.95), y + Inches(0.1), Inches(0.14), Inches(0.14), fill=ACCENT) txt(Inches(1.28), y, Inches(4.6), Inches(0.45), c, size=16.5, color=WHITE, bold=(i == 0)) # =========================================================================== # LUPEN (Projektionen) # =========================================================================== def lupe(cx, label, label_w): cyy = Inches(2.45) d = Inches(0.9) shp(MSO_SHAPE.OVAL, cx - d / 2, cyy - d / 2, d, d, fill=WHITE, line=NAVY, lw=Pt(4)) shp(MSO_SHAPE.OVAL, cx - d / 2 + Inches(0.13), cyy - d / 2 + Inches(0.12), Inches(0.17), Inches(0.13), fill=RECF) hw, hh = Inches(0.48), Inches(0.15) hcx, hcy = cx + d * 0.52, cyy + d * 0.52 shp(MSO_SHAPE.ROUNDED_RECTANGLE, hcx - hw / 2, hcy - hh / 2, hw, hh, fill=NAVY, rot=45) txt(cx - label_w / 2, cyy + d / 2 + Inches(0.16), label_w, Inches(0.6), label, size=14, color=WHITE, bold=True, align=PP_ALIGN.CENTER) return cyy + d / 2 lupes = [ (Inches(7.05), "Gruppen-Reporting", Inches(2.3)), (Inches(9.45), "Optimierung der Auslastung", Inches(2.3)), (Inches(11.55), "Abrechnungen", Inches(1.9)), ] lens_bottoms = [lupe(cx, lb, lw) for cx, lb, lw in lupes] # =========================================================================== # EVENTSTREAM (Pfeil) # =========================================================================== ay, ah = Inches(4.45), Inches(0.46) shp(MSO_SHAPE.RIGHT_ARROW, x0, ay, beltw, ah, fill=STREAM) acx = ay + ah / 2 txt(Inches(5.65), ay + Inches(0.04), Inches(2.0), ah - Inches(0.08), "Eventstream", size=14, color=WHITE, bold=True, align=PP_ALIGN.CENTER) # Verbinder Lupe -> Strom for (cx, _, _), lb_y in zip(lupes, lens_bottoms): shp(MSO_SHAPE.RECTANGLE, cx - Pt(0.5), lb_y, Pt(1), ay - lb_y, fill=LINEC) # =========================================================================== # RÖHRCHEN-STRECKE durch Maschine – unten # =========================================================================== belt_top = Inches(6.1) belt_h = Inches(0.30) for rx in (x0 - Inches(0.18), x1 - Inches(0.32)): shp(MSO_SHAPE.OVAL, rx, belt_top - Inches(0.10), Inches(0.5), Inches(0.5), fill=BELT, line=LINEC) shp(MSO_SHAPE.ROUNDED_RECTANGLE, x0, belt_top, beltw, belt_h, fill=BELT) mx, mw = Inches(5.45), Inches(2.45) my, mh = Inches(5.2), Inches(1.5) shp(MSO_SHAPE.ROUNDED_RECTANGLE, mx, my, mw, mh, fill=NAVY) shp(MSO_SHAPE.ROUNDED_RECTANGLE, mx + Inches(0.3), my + Inches(0.22), mw - Inches(0.6), Inches(0.32), fill=MID) shp(MSO_SHAPE.OVAL, mx + Inches(0.35), my + Inches(0.74), Inches(0.15), Inches(0.15), fill=TEAL) shp(MSO_SHAPE.OVAL, mx + Inches(0.6), my + Inches(0.74), Inches(0.15), Inches(0.15), fill=AMBER) shp(MSO_SHAPE.RECTANGLE, mx - Inches(0.02), belt_top - Inches(0.02), Inches(0.14), belt_h + Inches(0.04), fill=DARK) shp(MSO_SHAPE.RECTANGLE, mx + mw - Inches(0.12), belt_top - Inches(0.02), Inches(0.14), belt_h + Inches(0.04), fill=DARK) def tube(cx, liquid): bw, bh = Inches(0.22), Inches(0.6) bx, by = cx - bw / 2, belt_top - bh shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, by, bw, bh, fill=GLASS, line=LINEC, lw=Pt(0.75)) lh = Inches(0.25) shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx + Pt(1), belt_top - lh, bw - Pt(2), lh, fill=liquid) cw, ch = Inches(0.26), Inches(0.12) shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx - cw / 2, by - Inches(0.06), cw, ch, fill=DARK) cols = [ACCENT, TEAL, AMBER] pre_x = [1.55, 2.1, 2.65, 3.2, 3.75, 4.3, 4.85] post_x = [8.25, 8.8, 9.35, 9.9, 10.45, 11.0] for i, xv in enumerate(pre_x + post_x): tube(Inches(xv), cols[i % 3]) tube_top = belt_top - Inches(0.6) for xv in pre_x + post_x: shp(MSO_SHAPE.RECTANGLE, Inches(xv) - Pt(0.4), ay + ah, Pt(0.8), tube_top - (ay + ah), fill=THIN) shp(MSO_SHAPE.OVAL, Inches(xv) - Inches(0.05), acx - Inches(0.05), Inches(0.1), Inches(0.1), fill=AMBER) out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie4.pptx") prs.save(out) print("saved", out)