Skip to content

Commit

Permalink
Ubuntu template fix (#12)
Browse files Browse the repository at this point in the history
* Switched to unzipped templates to fix Ubuntu errors

* Improved docs & shows

* update compat
  • Loading branch information
matthijscox-asml authored Jan 27, 2023
1 parent c85961c commit 3aeac1c
Show file tree
Hide file tree
Showing 54 changed files with 339 additions and 124 deletions.
5 changes: 5 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
XMLDict = "228000da-037f-5747-90a9-8195ccbf91a5"

[compat]
DataStructures = "0.18"
EzXML = "1"
FileIO = "1"
Images = "0.25"
Tables = "1"
XMLDict = "0.4"
julia = "1.6"

Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
PPTX = "14a86994-10a4-4a7d-b9ad-ef6f3b1fac6a"
29 changes: 22 additions & 7 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,32 @@ Pages = ["api.md"]

## Example usage

```julia
You can build a presentation inside Julia:

```jldoctest
using PPTX, DataFrames
# Lets make a presentation
# note: this already adds a first slide with the title
pres = Presentation(; title="My First PowerPoint")
# What about a slide with some text
s1 = Slide(; title="My First Slide")
s2 = Slide(; title="My First Slide")
text = TextBox(; content="hello world!", offset_x=100, offset_y=100, size_x=150, size_y=20)
push!(s1, text)
push!(s2, text)
text2 = TextBox(; content="here we are again", offset_x=100, offset_y=120, size_x=150, size_y=20)
push!(s1, text2)
push!(pres, s1)
push!(s2, text2)
push!(pres, s2)
# Now lets add a picture and some text
cauli_pic = Picture(joinpath(PPTX.EXAMPLE_DIR,"pictures/cauliflower.jpg"))
cauli_pic = Picture(joinpath(PPTX.ASSETS_DIR,"cauliflower.jpg"))
text = TextBox(content="Look its a vegetable!")
s3 = Slide()
push!(s3, cauli_pic)
push!(s3, text)
# move picture 100 mm down and 100 mm right
julia_logo = Picture(joinpath(PPTX.EXAMPLE_DIR,"pictures/julia_logo.png"), offset_x=100, offset_y=100)
julia_logo = Picture(joinpath(PPTX.ASSETS_DIR,"julia_logo.png"), offset_x=100, offset_y=100)
push!(s3, julia_logo)
push!(pres, s3)
Expand All @@ -47,5 +49,18 @@ my_table = Table(df; offset_x=60, offset_y=80, size_x=150, size_y=40)
push!(s4, my_table)
push!(pres, s4)
pres
# output
Presentation with 4 slides
title is "My First PowerPoint"
author is "unknown"
```

Finally you can write the PPTX file with `PPTX.write`:

```julia
PPTX.write("example.pptx", pres, overwrite = true, open_ppt=true)
```
18 changes: 17 additions & 1 deletion src/AbstractShape.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,20 @@ set_rid!(s::AbstractShape, i::Int) = nothing
has_rid(s::AbstractShape) = false

## If AbstractShape does not have rId return 0
rid(s::AbstractShape) = 0
rid(s::AbstractShape) = 0

# default show used by Array show
function Base.show(io::IO, shape::AbstractShape)
compact = get(io, :compact, true)
return print(io, _show_string(shape, compact))
end

# default show used by display() on the REPL
function Base.show(io::IO, mime::MIME"text/plain", shape::AbstractShape)
compact = get(io, :compact, false)
return print(io, _show_string(shape, compact))
end

function _show_string(shape::AbstractShape, compact::Bool)
return "$(typeof(shape))"
end
9 changes: 0 additions & 9 deletions src/PPTX.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@

"""
Interface functions:
* `Presentation`: Presentation constructor, used for making a presentation.
* `Slide`: Slide constructor, used for making a slide.
* `TextBox`: TextBox constructor, used for adding text to slides.
* `Picture`: Picture constructor, used for adding pictures to slides.
* `write`: write a presentation to a file.
"""
module PPTX

using XMLDict
Expand Down
31 changes: 21 additions & 10 deletions src/Picture.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@ Picture(source::String; top::Int=0, left::Int=0, size::Int = 40)
* `top::Int` mm from the top
* `left::Int` mm from the left
Internally the sizes are converted EMUs.
# Examples
```julia
julia> using PPTX
julia> img = Picture(joinpath(PPTX.EXAMPLE_DIR, "pictures/cauliflower.jpg"))
julia> slide = Slide()
julia> push!(slide, img)
julia> pres = Presentation()
julia> img = Picture(joinpath(PPTX.ASSETS_DIR, "cauliflower.jpg"))
Picture
source is "./cauliflower.jpg"
offset_x is 0 EMUs
offset_y is 0 EMUs
size_x is 1440000 EMUs
size_y is 1475072 EMUs
julia> push!(pres, slide)
julia> write("cauliflower.pptx", pres)
```
"""
struct Picture <: AbstractShape
Expand Down Expand Up @@ -53,6 +52,18 @@ set_rid(s::Picture, i::Int) = Picture(s.source, s.offset_x, s.offset_y, s.size_x
rid(s::Picture) = s.rid
has_rid(s::Picture) = true

function _show_string(p::Picture, compact::Bool)
show_string = "Picture"
if !compact
show_string *= "\n source is \"$(p.source)\""
show_string *= "\n offset_x is $(p.offset_x) EMUs"
show_string *= "\n offset_y is $(p.offset_y) EMUs"
show_string *= "\n size_x is $(p.size_x) EMUs"
show_string *= "\n size_y is $(p.size_y) EMUs"
end
return show_string
end

function make_xml(shape::Picture, id::Int)
cNvPr = Dict("p:cNvPr" => [Dict("id" => "$id"), Dict("name" => "Picture")])
cNvPicPr = Dict("p:cNvPicPr" => Dict("a:picLocks" => Dict("noChangeAspect" => "1")))
Expand Down
52 changes: 35 additions & 17 deletions src/Presentation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,24 @@ Type to contain the final presentation you want to write to .pptx.
If `isempty(slides)` then we add a first slide with the Title slide layout.
# Examples
```julia
```jldoctest
julia> using PPTX
julia> pres = Presentation(; title = "My Presentation")
Presentation with 1 slide
title is "My Presentation"
author is "unknown"
julia> slide = Slide()
julia> text = TextBox("Hello world!")
julia> push!(slide, text)
julia> push!(pres, slide)
julia> write("hello_world.pptx", pres)
```
"""
struct Presentation
title::String
author::String
slides::Vector{Slide}
function Presentation(
slides::Vector{Slide}, author::String, title::String,
)
function Presentation(slides::Vector{Slide}, author::String, title::String)
pres = new(title, author, Slide[])
if isempty(slides)
slides = [Slide(;title=title, layout=TITLE_SLIDE_LAYOUT)]
slides = [Slide(; title=title, layout=TITLE_SLIDE_LAYOUT)]
end
for slide in slides
push!(pres, slide)
Expand All @@ -50,9 +42,7 @@ slides(p::Presentation) = p.slides

# keyword argument constructor
function Presentation(
slides::Vector{Slide}=Slide[];
title::String="unknown",
author::String="unknown",
slides::Vector{Slide}=Slide[]; title::String="unknown", author::String="unknown"
)
return Presentation(slides, author, title)
end
Expand All @@ -70,6 +60,34 @@ function Base.push!(pres::Presentation, slide::Slide)
return push!(slides(pres), slide)
end

# default show used by Array show
function Base.show(io::IO, p::Presentation)
compact = get(io, :compact, true)
return print(io, _show_string(p, compact))
end

# default show used by display() on the REPL
function Base.show(io::IO, mime::MIME"text/plain", p::Presentation)
compact = get(io, :compact, false)
return print(io, _show_string(p, compact))
end

function _show_string(p::Presentation, compact::Bool)
show_string = ""
nslides = length(p.slides)
if nslides == 1
slide_string = "slide"
else
slide_string = "slides"
end
show_string *= "Presentation with $(nslides) $slide_string"
if !compact
show_string *= "\n title is \"$(p.title)\""
show_string *= "\n author is \"$(p.author)\""
end
return show_string
end

function make_relationships(p::Presentation)::AbstractDict
ids = ["rId1", "rId2", "rId3", "rId4", "rId5"]
relationship_tag_begin = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/"
Expand Down
15 changes: 10 additions & 5 deletions src/Slide.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,21 @@ You can `push!` any `AbstractShape` types into this slide, such as a `TextBox` o
julia> using PPTX
julia> slide = Slide(; title="Hello Title", layout=2)
Slide("Hello Title", PPTX.AbstractShape[], 0, 2)
julia> text = TextBox("Hello world!")
TextBox
content is "Hello world!"
offset_x is 1800000 EMUs
offset_y is 1800000 EMUs
size_x is 1440000 EMUs
size_y is 1080000 EMUs
julia> push!(slide, text)
julia> push!(slide, text);
julia> pres = Presentation()
julia> slide
Slide("Hello Title", PPTX.AbstractShape[TextBox], 0, 2)
julia> push!(pres, slide)
julia> write("hello_world.pptx", pres)
```
"""
mutable struct Slide
Expand Down
51 changes: 51 additions & 0 deletions src/Tables.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
"""
```julia
Table(;
content,
offset_x::Real = 50,
offset_y::Real = 50,
size_x::Real = 150,
size_y::Real = 100,
)
```
A Table to be used on a Slide.
The content can be anything that adheres to a `Tables.jl` interface.
Offsets and sizes are in millimeters, but will be converted to EMU.
# Examples
```jldoctest
julia> using PPTX, DataFrames
julia> df = DataFrame(a = [1,2], b = [3,4], c = [5,6])
2×3 DataFrame
Row │ a b c
│ Int64 Int64 Int64
─────┼─────────────────────
1 │ 1 3 5
2 │ 2 4 6
julia> t = Table(content=df, size_x=30)
Table
content isa DataFrame
offset_x is 1800000 EMUs
offset_y is 1800000 EMUs
size_x is 1080000 EMUs
size_y is 3600000 EMUs
```
"""
struct Table <: AbstractShape
content # anything that adheres to Tables.jl interfaces
offset_x::Int # EMUs
Expand Down Expand Up @@ -44,6 +83,18 @@ Tables.rows(t::Table) = Tables.rows(t.content)
ncols(t::Table) = length(Tables.columns(t))
nrows(t::Table) = length(Tables.rows(t))

function _show_string(t::Table, compact::Bool)
show_string = "Table"
if !compact
show_string *= "\n content isa $(typeof(t.content))"
show_string *= "\n offset_x is $(t.offset_x) EMUs"
show_string *= "\n offset_y is $(t.offset_y) EMUs"
show_string *= "\n size_x is $(t.size_x) EMUs"
show_string *= "\n size_y is $(t.size_y) EMUs"
end
return show_string
end

function make_xml(t::Table, id::Integer)
nvGraphicFramePr = make_nvGraphicFramePr(t, id)
xfrm = make_xfrm(t)
Expand Down
31 changes: 20 additions & 11 deletions src/TextBox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,17 @@ A TextBox to be used on a Slide.
Offsets and sizes are in millimeters, but will be converted to EMU.
# Examples
```julia
```jldoctest
julia> using PPTX
julia> text = TextBox(content="Hello world!")
julia> slide = Slide()
julia> push!(slide, text)
julia> pres = Presentation()
julia> text = TextBox(content="Hello world!", size_x=30)
TextBox
content is "Hello world!"
offset_x is 1800000 EMUs
offset_y is 1800000 EMUs
size_x is 1080000 EMUs
size_y is 1080000 EMUs
julia> push!(pres, slide)
julia> write("hello_world.pptx", pres)
```
"""
struct TextBox <: AbstractShape
Expand Down Expand Up @@ -106,6 +103,18 @@ end

TextBox(content::String; kwargs...) = TextBox(;content=content, kwargs...)

function _show_string(p::TextBox, compact::Bool)
show_string = "TextBox"
if !compact
show_string *= "\n content is \"$(String(p.content))\""
show_string *= "\n offset_x is $(p.offset_x) EMUs"
show_string *= "\n offset_y is $(p.offset_y) EMUs"
show_string *= "\n size_x is $(p.size_x) EMUs"
show_string *= "\n size_y is $(p.size_y) EMUs"
end
return show_string
end

function text_style_xml(t::TextBody)
style = [Dict("lang" => "en-US")]
if t.style["bold"]
Expand Down
2 changes: 1 addition & 1 deletion src/constants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const _EMUS_PER_MM = 36000
const _EMUS_PER_PT = 12700

const TEMPLATE_DIR = abspath(joinpath(@__DIR__, "..", "templates"))
const EXAMPLE_DIR = abspath(joinpath(@__DIR__, "..", "examples"))
const ASSETS_DIR = abspath(joinpath(@__DIR__, "..", "assets"))
const TESTDATA_DIR = abspath(joinpath(@__DIR__, "..", "test/testdata"))

# we use layoutSlide1 for the first title slide, and layoutSlide2 for all other slides
Expand Down
Loading

2 comments on commit 3aeac1c

@matthijscox-asml
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/76719

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.0 -m "<description of version>" 3aeac1c16bf727da623bdf153c4c2c16e917b9f7
git push origin v0.5.0

Also, note the warning: This looks like a new registration that registers version 0.5.0.
Ideally, you should register an initial release with 0.0.1, 0.1.0 or 1.0.0 version numbers
This can be safely ignored. However, if you want to fix this you can do so. Call register() again after making the fix. This will update the Pull request.

Please sign in to comment.