2018-09-27 20:55:58 +03:00
|
|
|
/*
|
|
|
|
* This file is subject to the terms and conditions defined in
|
|
|
|
* file 'LICENSE.md', which is part of this source code package.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package creator
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TOCLine struct {
|
|
|
|
sp *StyledParagraph
|
|
|
|
|
2018-09-28 19:30:46 +03:00
|
|
|
Number TextChunk
|
|
|
|
Title TextChunk
|
|
|
|
Page TextChunk
|
|
|
|
Separator TextChunk
|
2018-09-27 20:55:58 +03:00
|
|
|
|
2018-09-28 19:54:09 +03:00
|
|
|
level uint
|
|
|
|
offset float64
|
|
|
|
levelOffset float64
|
2018-09-30 19:06:08 +03:00
|
|
|
|
|
|
|
// Positioning: relative/absolute.
|
|
|
|
positioning positioning
|
2018-09-27 20:55:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewTOCLine(number, title, page string, level uint) *TOCLine {
|
|
|
|
style := NewTextStyle()
|
|
|
|
|
|
|
|
return NewStyledTOCLine(
|
2018-09-28 19:30:46 +03:00
|
|
|
TextChunk{
|
|
|
|
Text: number,
|
|
|
|
Style: style,
|
|
|
|
},
|
|
|
|
TextChunk{
|
|
|
|
Text: title,
|
|
|
|
Style: style,
|
|
|
|
},
|
|
|
|
TextChunk{
|
|
|
|
Text: page,
|
|
|
|
Style: style,
|
|
|
|
},
|
2018-09-27 20:55:58 +03:00
|
|
|
level,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewStyledTOCLine(number, title, page TextChunk, level uint) *TOCLine {
|
|
|
|
style := NewTextStyle()
|
|
|
|
|
|
|
|
sp := NewStyledParagraph("", style)
|
|
|
|
sp.SetEnableWrap(true)
|
|
|
|
sp.SetTextAlignment(TextAlignmentLeft)
|
2018-09-30 19:06:08 +03:00
|
|
|
sp.SetMargins(0, 0, 2, 2)
|
2018-09-27 20:55:58 +03:00
|
|
|
|
|
|
|
tl := &TOCLine{
|
|
|
|
sp: sp,
|
2018-09-28 19:30:46 +03:00
|
|
|
Number: number,
|
|
|
|
Title: title,
|
|
|
|
Page: page,
|
|
|
|
Separator: TextChunk{
|
2018-09-27 20:55:58 +03:00
|
|
|
Text: ".",
|
|
|
|
Style: style,
|
|
|
|
},
|
2018-09-28 19:54:09 +03:00
|
|
|
offset: 0,
|
|
|
|
level: level,
|
|
|
|
levelOffset: 10,
|
2018-09-27 20:55:58 +03:00
|
|
|
}
|
|
|
|
|
2018-09-28 19:54:09 +03:00
|
|
|
sp.margins.left = tl.offset + float64(tl.level-1)*tl.levelOffset
|
2018-09-27 20:55:58 +03:00
|
|
|
sp.beforeRender = tl.prepareParagraph
|
|
|
|
return tl
|
|
|
|
}
|
|
|
|
|
2018-09-28 19:54:09 +03:00
|
|
|
func (tl *TOCLine) Level() uint {
|
|
|
|
return tl.level
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tl *TOCLine) SetLevel(level uint) {
|
|
|
|
tl.level = level
|
|
|
|
tl.sp.margins.left = tl.offset + float64(tl.level-1)*tl.levelOffset
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tl *TOCLine) LevelOffset() float64 {
|
|
|
|
return tl.levelOffset
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tl *TOCLine) SetLevelOffset(levelOffset float64) {
|
|
|
|
tl.levelOffset = levelOffset
|
|
|
|
tl.sp.margins.left = tl.offset + float64(tl.level-1)*tl.levelOffset
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetMargins returns the margins of the TOC line: left, right, top, bottom.
|
|
|
|
func (tl *TOCLine) GetMargins() (float64, float64, float64, float64) {
|
|
|
|
m := &tl.sp.margins
|
|
|
|
return tl.offset, m.right, m.top, m.bottom
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetMargins sets the margins TOC line.
|
|
|
|
func (tl *TOCLine) SetMargins(left, right, top, bottom float64) {
|
|
|
|
tl.offset = left
|
|
|
|
|
|
|
|
m := &tl.sp.margins
|
|
|
|
m.left = tl.offset + float64(tl.level-1)*tl.levelOffset
|
|
|
|
m.right = right
|
|
|
|
m.top = top
|
|
|
|
m.bottom = bottom
|
|
|
|
}
|
|
|
|
|
2018-09-27 20:55:58 +03:00
|
|
|
func (tl *TOCLine) prepareParagraph(sp *StyledParagraph, ctx DrawContext) {
|
2018-09-28 19:30:46 +03:00
|
|
|
// Add text chunks to the paragraph
|
|
|
|
title := tl.Title.Text
|
|
|
|
if tl.Number.Text != "" {
|
|
|
|
title = " " + title
|
2018-09-27 20:55:58 +03:00
|
|
|
}
|
2018-09-28 19:30:46 +03:00
|
|
|
title += " "
|
2018-09-27 20:55:58 +03:00
|
|
|
|
2018-09-28 19:30:46 +03:00
|
|
|
page := tl.Page.Text
|
|
|
|
if page != "" {
|
|
|
|
page = " " + page
|
2018-09-27 20:55:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
sp.chunks = []TextChunk{
|
2018-09-28 19:30:46 +03:00
|
|
|
tl.Number,
|
|
|
|
TextChunk{
|
|
|
|
Text: title,
|
|
|
|
Style: tl.Title.Style,
|
|
|
|
},
|
|
|
|
TextChunk{
|
|
|
|
Text: page,
|
|
|
|
Style: tl.Page.Style,
|
|
|
|
},
|
2018-09-27 20:55:58 +03:00
|
|
|
}
|
2018-09-28 19:54:09 +03:00
|
|
|
|
2018-09-27 20:55:58 +03:00
|
|
|
sp.SetEncoder(sp.encoder)
|
|
|
|
sp.wrapText()
|
|
|
|
|
2018-09-28 19:30:46 +03:00
|
|
|
// Insert separator
|
2018-09-27 20:55:58 +03:00
|
|
|
l := len(sp.lines)
|
|
|
|
if l == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
availWidth := ctx.Width*1000 - sp.getTextLineWidth(sp.lines[l-1])
|
2018-09-28 19:30:46 +03:00
|
|
|
sepWidth := sp.getTextLineWidth([]TextChunk{tl.Separator})
|
2018-09-27 20:55:58 +03:00
|
|
|
sepCount := int(availWidth / sepWidth)
|
2018-09-28 19:30:46 +03:00
|
|
|
sepText := strings.Repeat(tl.Separator.Text, sepCount)
|
|
|
|
sepStyle := tl.Separator.Style
|
2018-09-27 20:55:58 +03:00
|
|
|
|
2018-09-28 19:30:46 +03:00
|
|
|
sp.Insert(2, sepText, sepStyle)
|
2018-09-27 20:55:58 +03:00
|
|
|
|
|
|
|
// Push page numbers to the end of the line
|
|
|
|
availWidth = availWidth - float64(sepCount)*sepWidth
|
|
|
|
if availWidth > 500 {
|
2018-09-28 19:30:46 +03:00
|
|
|
spaceMetrics, found := sepStyle.Font.GetGlyphCharMetrics("space")
|
2018-09-27 20:55:58 +03:00
|
|
|
if found && availWidth > spaceMetrics.Wx {
|
|
|
|
spaces := int(availWidth / spaceMetrics.Wx)
|
|
|
|
if spaces > 0 {
|
2018-09-28 19:30:46 +03:00
|
|
|
style := sepStyle
|
2018-09-27 20:55:58 +03:00
|
|
|
style.FontSize = 1
|
|
|
|
sp.Insert(2, strings.Repeat(" ", spaces), style)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tl *TOCLine) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext, error) {
|
|
|
|
origCtx := ctx
|
|
|
|
|
|
|
|
blocks, ctx, err := tl.sp.GeneratePageBlocks(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return blocks, ctx, err
|
|
|
|
}
|
|
|
|
|
2018-09-30 19:06:08 +03:00
|
|
|
if tl.positioning.isRelative() {
|
2018-09-27 20:55:58 +03:00
|
|
|
// Move back X to same start of line.
|
|
|
|
ctx.X = origCtx.X
|
|
|
|
}
|
|
|
|
|
2018-09-30 19:06:08 +03:00
|
|
|
if tl.positioning.isAbsolute() {
|
2018-09-27 20:55:58 +03:00
|
|
|
// If absolute: return original context.
|
|
|
|
return blocks, origCtx, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return blocks, ctx, nil
|
|
|
|
}
|