2017-07-05 23:10:57 +00: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 (
|
2017-07-07 15:08:43 +00:00
|
|
|
"errors"
|
2017-07-05 23:10:57 +00:00
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/unidoc/unidoc/common"
|
|
|
|
"github.com/unidoc/unidoc/pdf/model/fonts"
|
|
|
|
)
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
type Chapter struct {
|
2017-07-05 23:10:57 +00:00
|
|
|
number int
|
|
|
|
title string
|
|
|
|
heading *paragraph
|
|
|
|
|
|
|
|
subchapters int
|
|
|
|
|
|
|
|
contents []Drawable
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Show chapter numbering
|
|
|
|
showNumbering bool
|
|
|
|
|
|
|
|
// Include in TOC.
|
|
|
|
includeInTOC bool
|
|
|
|
|
2017-07-05 23:10:57 +00:00
|
|
|
// Positioning: relative / absolute.
|
|
|
|
positioning positioning
|
|
|
|
|
|
|
|
// Absolute coordinates (when in absolute mode).
|
|
|
|
xPos, yPos float64
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Margins to be applied around the block when drawing on Page.
|
2017-07-05 23:10:57 +00:00
|
|
|
margins margins
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Reference to the creator's TOC.
|
|
|
|
toc *TableOfContents
|
2017-07-05 23:10:57 +00:00
|
|
|
}
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
func (c *Creator) NewChapter(title string) *Chapter {
|
|
|
|
chap := &Chapter{}
|
2017-07-05 23:10:57 +00:00
|
|
|
|
|
|
|
c.chapters++
|
|
|
|
chap.number = c.chapters
|
|
|
|
chap.title = title
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
chap.showNumbering = true
|
|
|
|
chap.includeInTOC = true
|
|
|
|
|
2017-07-05 23:10:57 +00:00
|
|
|
heading := fmt.Sprintf("%d. %s", c.chapters, title)
|
|
|
|
p := NewParagraph(heading)
|
|
|
|
p.SetFontSize(16)
|
|
|
|
p.SetFont(fonts.NewFontHelvetica()) // bold?
|
|
|
|
|
|
|
|
chap.heading = p
|
|
|
|
chap.contents = []Drawable{}
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Keep a reference for toc.
|
|
|
|
chap.toc = c.toc
|
|
|
|
|
2017-07-05 23:10:57 +00:00
|
|
|
return chap
|
|
|
|
}
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Set flag to indicate whether or not to show chapter numbers as part of title.
|
|
|
|
func (chap *Chapter) SetShowNumbering(show bool) {
|
|
|
|
if show {
|
|
|
|
heading := fmt.Sprintf("%d. %s", chap.number, chap.title)
|
|
|
|
chap.heading.SetText(heading)
|
|
|
|
} else {
|
|
|
|
heading := fmt.Sprintf("%s", chap.title)
|
|
|
|
chap.heading.SetText(heading)
|
|
|
|
}
|
|
|
|
chap.showNumbering = show
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set flag to indicate whether or not to include in tOC.
|
|
|
|
func (chap *Chapter) SetIncludeInTOC(includeInTOC bool) {
|
|
|
|
chap.includeInTOC = includeInTOC
|
|
|
|
}
|
|
|
|
|
2017-07-07 15:08:43 +00:00
|
|
|
// Get access to the heading paragraph to address style etc.
|
2017-07-06 16:26:22 +00:00
|
|
|
func (chap *Chapter) GetHeading() *paragraph {
|
|
|
|
return chap.heading
|
|
|
|
}
|
|
|
|
|
2017-07-05 23:10:57 +00:00
|
|
|
// Set absolute coordinates.
|
2017-07-06 16:26:22 +00:00
|
|
|
func (chap *Chapter) SetPos(x, y float64) {
|
2017-07-05 23:10:57 +00:00
|
|
|
chap.positioning = positionAbsolute
|
|
|
|
chap.xPos = x
|
|
|
|
chap.yPos = y
|
|
|
|
}
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Set chapter Margins. Typically not needed as the Page Margins are used.
|
|
|
|
func (chap *Chapter) SetMargins(left, right, top, bottom float64) {
|
2017-07-05 23:10:57 +00:00
|
|
|
chap.margins.left = left
|
|
|
|
chap.margins.right = right
|
|
|
|
chap.margins.top = top
|
|
|
|
chap.margins.bottom = bottom
|
|
|
|
}
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Get chapter Margins: left, right, top, bottom.
|
|
|
|
func (chap *Chapter) GetMargins() (float64, float64, float64, float64) {
|
2017-07-05 23:10:57 +00:00
|
|
|
return chap.margins.left, chap.margins.right, chap.margins.top, chap.margins.bottom
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a new drawable to the chapter.
|
2017-07-07 15:08:43 +00:00
|
|
|
func (chap *Chapter) Add(d Drawable) error {
|
2017-07-05 23:10:57 +00:00
|
|
|
if Drawable(chap) == d {
|
|
|
|
common.Log.Debug("ERROR: Cannot add itself")
|
2017-07-07 15:08:43 +00:00
|
|
|
return errors.New("Range check error")
|
2017-07-05 23:10:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch d.(type) {
|
2017-07-06 16:26:22 +00:00
|
|
|
case *Chapter:
|
2017-07-05 23:10:57 +00:00
|
|
|
common.Log.Debug("Error: Cannot add chapter to a chapter")
|
2017-07-07 15:08:43 +00:00
|
|
|
return errors.New("Type check error")
|
|
|
|
case *paragraph, *image, *Block, *subchapter, *Table:
|
2017-07-05 23:10:57 +00:00
|
|
|
chap.contents = append(chap.contents, d)
|
|
|
|
default:
|
|
|
|
common.Log.Debug("Unsupported: %T", d)
|
2017-07-07 15:08:43 +00:00
|
|
|
return errors.New("Type check error")
|
2017-07-05 23:10:57 +00:00
|
|
|
}
|
2017-07-07 15:08:43 +00:00
|
|
|
|
|
|
|
return nil
|
2017-07-05 23:10:57 +00:00
|
|
|
}
|
|
|
|
|
2017-07-06 16:26:22 +00:00
|
|
|
// Generate the Page blocks. Multiple blocks are generated if the contents wrap over
|
|
|
|
// multiple pages.
|
|
|
|
func (chap *Chapter) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext, error) {
|
2017-07-05 23:10:57 +00:00
|
|
|
blocks, ctx, err := chap.heading.GeneratePageBlocks(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return blocks, ctx, err
|
|
|
|
}
|
2017-07-06 16:26:22 +00:00
|
|
|
if len(blocks) > 1 {
|
|
|
|
ctx.Page++ // Did not fit, moved to new Page block.
|
|
|
|
}
|
|
|
|
|
|
|
|
if chap.includeInTOC {
|
|
|
|
// Add to TOC.
|
|
|
|
chap.toc.add(chap.title, chap.number, 0, ctx.Page)
|
|
|
|
}
|
2017-07-05 23:10:57 +00:00
|
|
|
|
|
|
|
for _, d := range chap.contents {
|
|
|
|
newBlocks, c, err := d.GeneratePageBlocks(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return blocks, ctx, err
|
|
|
|
}
|
|
|
|
if len(newBlocks) < 1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// The first block is always appended to the last..
|
|
|
|
blocks[len(blocks)-1].mergeBlocks(newBlocks[0])
|
|
|
|
blocks = append(blocks, newBlocks[1:]...)
|
|
|
|
|
|
|
|
ctx = c
|
|
|
|
}
|
|
|
|
|
|
|
|
return blocks, ctx, nil
|
|
|
|
}
|