Răsfoiți Sursa

добавил простые аттрибуты для таблицы, строки, столбца и ячейки

kpmy 10 ani în urmă
părinte
comite
f118007f08

+ 8 - 0
mappers/attr/base.go

@@ -76,3 +76,11 @@ func (e *easy) apply(wr model.Writer) {
 		}
 	}
 }
+
+func triggerBoolAttr(n model.AttrName) func(v value) {
+	return func(v value) {
+		if x := v.data.(bool); x {
+			v.wr.Attr(n, true)
+		}
+	}
+}

+ 21 - 0
mappers/attr/extra.go

@@ -0,0 +1,21 @@
+package attr
+
+import (
+	"fmt"
+	"github.com/kpmy/ypk/assert"
+	"image/color"
+	"strconv"
+)
+
+type Border struct {
+	Width float64
+	Color color.Color
+	Style string
+}
+
+func (bb Border) String() string {
+	assert.For(bb.Style != "", 20)
+	assert.For(bb.Color != nil, 21)
+	r, g, b, _ := bb.Color.RGBA()
+	return fmt.Sprint(strconv.FormatFloat(bb.Width, 'f', 8, 64)+"cm", " ", bb.Style, " ", fmt.Sprintf("#%02X%02X%02X", uint8(r), uint8(g), uint8(b)))
+}

+ 135 - 0
mappers/attr/table.go

@@ -0,0 +1,135 @@
+package attr
+
+import (
+	"odf/model"
+	"odf/xmlns/fo"
+	"odf/xmlns/style"
+	"odf/xmlns/table"
+)
+
+type TableAttributes struct {
+	named
+	easy
+}
+
+func (t *TableAttributes) Equal(_a Attributes) (ok bool) {
+	a, ok := _a.(*TableAttributes)
+	if ok {
+		ok = t.equal(&a.easy)
+	}
+	return
+}
+
+func (t *TableAttributes) Fit() model.LeafName { return table.Table }
+
+func (t *TableAttributes) Write(wr model.Writer) {
+	wr.Attr(style.Family, style.FamilyTable)
+	wr.WritePos(New(style.TableProperties))
+	t.apply(wr)
+}
+
+func (t *TableAttributes) BorderModel(m string) *TableAttributes {
+	t.put(table.BorderModel, m, nil)
+	return t
+}
+
+func (t *TableAttributes) AlignLeft() *TableAttributes {
+	t.put(table.Align, table.AlignLeft, nil)
+	return t
+}
+
+func (t *TableAttributes) AlignRight() *TableAttributes {
+	t.put(table.Align, table.AlignRight, nil)
+	return t
+}
+
+func (t *TableAttributes) AlignCenter() *TableAttributes {
+	t.put(table.Align, table.AlignCenter, nil)
+	return t
+}
+
+func (t *TableAttributes) Width(w float64) *TableAttributes {
+	t.put(style.Width, w, nil)
+	return t
+}
+
+type TableRowAttributes struct {
+	named
+	easy
+}
+
+func (t *TableRowAttributes) Equal(_a Attributes) (ok bool) {
+	a, ok := _a.(*TableRowAttributes)
+	if ok {
+		ok = t.equal(&a.easy)
+	}
+	return
+}
+
+func (t *TableRowAttributes) Fit() model.LeafName { return table.TableRow }
+
+func (t *TableRowAttributes) Write(wr model.Writer) {
+	wr.Attr(style.Family, style.FamilyTableRow)
+	wr.WritePos(New(style.TableRowProperties))
+	t.apply(wr)
+}
+
+func (t *TableRowAttributes) UseOptimalRowHeight() *TableRowAttributes {
+	t.put(style.UseOptimalRowHeight, true, triggerBoolAttr(style.UseOptimalRowHeight))
+	return t
+}
+
+type TableColumnAttributes struct {
+	named
+	easy
+}
+
+func (t *TableColumnAttributes) Equal(_a Attributes) (ok bool) {
+	a, ok := _a.(*TableColumnAttributes)
+	if ok {
+		ok = t.equal(&a.easy)
+	}
+	return
+}
+
+func (t *TableColumnAttributes) Fit() model.LeafName { return table.TableColumn }
+
+func (t *TableColumnAttributes) Write(wr model.Writer) {
+	wr.Attr(style.Family, style.FamilyTableColumn)
+	wr.WritePos(New(style.TableColumnProperties))
+	t.apply(wr)
+}
+
+func (t *TableColumnAttributes) UseOptimalColumnWidth() *TableColumnAttributes {
+	t.put(style.UseOptimalColumnWidth, true, triggerBoolAttr(style.UseOptimalColumnWidth))
+	return t
+}
+
+type TableCellAttributes struct {
+	named
+	easy
+}
+
+func (t *TableCellAttributes) Equal(_a Attributes) (ok bool) {
+	a, ok := _a.(*TableCellAttributes)
+	if ok {
+		ok = t.equal(&a.easy)
+	}
+	return
+}
+
+func (t *TableCellAttributes) Fit() model.LeafName { return table.TableCell }
+
+func (t *TableCellAttributes) Write(wr model.Writer) {
+	wr.Attr(style.Family, style.FamilyTableCell)
+	wr.WritePos(New(style.TableCellProperties))
+	t.apply(wr)
+}
+
+func (t *TableCellAttributes) Border(b Border) *TableCellAttributes {
+	t.put(fo.BorderRight, b.String(), nil)
+	t.put(fo.BorderLeft, b.String(), nil)
+	t.put(fo.BorderTop, b.String(), nil)
+	t.put(fo.BorderBottom, b.String(), nil)
+	return t
+}

+ 33 - 0
mappers/table.go

@@ -2,6 +2,7 @@ package mappers
 
 import (
 	"github.com/kpmy/ypk/assert"
+	"odf/mappers/attr"
 	"odf/model"
 	"odf/xmlns/table"
 )
@@ -42,20 +43,36 @@ func (t *TableMapper) Write(name string, rows, cols int) {
 	wr.Pos(t.fm.root)
 	this.Root = wr.WritePos(New(table.Table))
 	wr.Attr(table.Name, name)
+	t.fm.attr.Fit(table.Table, func(a attr.Attributes) {
+		wr.Attr(table.StyleName, a.Name())
+	})
 	for i := 0; i < this.Columns; i++ {
 		col := New(table.TableColumn)
 		this.colsCache = append(this.colsCache, col)
 		this.cellCache = append(this.cellCache, make([]model.Leaf, 0))
 		wr.Write(col)
+		cwr := t.newWriter(wr)
+		cwr.Pos(col)
+		t.fm.attr.Fit(table.TableColumn, func(a attr.Attributes) {
+			cwr.Attr(table.StyleName, a.Name())
+		})
 	}
 	for i := 0; i < this.Rows; i++ {
 		rwr := t.newWriter(wr)
 		row := rwr.WritePos(New(table.TableRow))
+		t.fm.attr.Fit(table.TableRow, func(a attr.Attributes) {
+			rwr.Attr(table.StyleName, a.Name())
+		})
 		this.rowCache = append(this.rowCache, row)
 		for j := 0; j < this.Columns; j++ {
 			cell := New(table.TableCell)
 			this.cellCache[j] = append(this.cellCache[j], cell)
 			rwr.Write(cell)
+			cwr := t.newWriter(rwr)
+			cwr.Pos(cell)
+			t.fm.attr.Fit(table.TableCell, func(a attr.Attributes) {
+				cwr.Attr(table.StyleName, a.Name())
+			})
 		}
 	}
 }
@@ -67,11 +84,19 @@ func (t *TableMapper) WriteRows(this *Table, rows int) {
 	for i := 0; i < rows; i++ {
 		wr.Pos(this.Root)
 		row := wr.WritePos(New(table.TableRow))
+		t.fm.attr.Fit(table.TableRow, func(a attr.Attributes) {
+			wr.Attr(table.StyleName, a.Name())
+		})
 		this.rowCache = append(this.rowCache, row)
 		for j := 0; j < this.Columns; j++ {
 			cell := New(table.TableCell)
 			this.cellCache[j] = append(this.cellCache[j], cell)
 			wr.Write(cell)
+			cwr := t.newWriter(wr)
+			cwr.Pos(cell)
+			t.fm.attr.Fit(table.TableCell, func(a attr.Attributes) {
+				cwr.Attr(table.StyleName, a.Name())
+			})
 		}
 		this.Rows++
 	}
@@ -88,6 +113,9 @@ func (t *TableMapper) WriteColumns(this *Table, cols int) {
 	for i := 0; i < cols; i++ {
 		wr.Pos(this.Root)
 		col := wr.WritePos(New(table.TableColumn), last)
+		t.fm.attr.Fit(table.TableColumn, func(a attr.Attributes) {
+			wr.Attr(table.StyleName, a.Name())
+		})
 		this.colsCache = append(this.colsCache, col)
 		this.cellCache = append(this.cellCache, make([]model.Leaf, 0))
 		this.Columns++
@@ -107,6 +135,11 @@ func (t *TableMapper) WriteCells(this *Table, _row int, cells int) {
 		cell := New(table.TableCell)
 		this.cellCache[i] = append(this.cellCache[i], cell)
 		wr.Write(cell)
+		cwr := t.newWriter(wr)
+		cwr.Pos(cell)
+		t.fm.attr.Fit(table.TableCell, func(a attr.Attributes) {
+			cwr.Attr(table.StyleName, a.Name())
+		})
 	}
 }
 

+ 18 - 0
model/stub/simple_attrs.go

@@ -35,6 +35,24 @@ func (a *IntAttr) MarshalXMLAttr(name xml.Name) (xa xml.Attr, err error) {
 	return
 }
 
+type BoolAttr struct {
+	Value bool
+}
+
+func (a *BoolAttr) String() string {
+	if a.Value {
+		return "true"
+	} else {
+		return "false"
+	}
+}
+
+func (a *BoolAttr) MarshalXMLAttr(name xml.Name) (xa xml.Attr, err error) {
+	xa.Name = name
+	xa.Value = a.String()
+	return
+}
+
 type MeasureAttr struct {
 	Value float64
 }

+ 3 - 1
model/stub/simple_riders.go

@@ -177,7 +177,7 @@ func validateAttr(n model.AttrName, val string) {
 			found = true
 		}
 	}
-	assert.For(found, 60)
+	assert.For(found, 60, n, val)
 }
 
 func castAttr(n model.AttrName, i interface{}) (ret model.Attribute) {
@@ -197,6 +197,8 @@ func castAttr(n model.AttrName, i interface{}) (ret model.Attribute) {
 		ret = &MeasureAttr{Value: i.(float64)}
 	case xmlns.COLOR:
 		ret = &ColorAttr{Value: i.(color.Color)}
+	case xmlns.BOOL:
+		ret = &BoolAttr{Value: i.(bool)}
 	default:
 		halt.As(100, typ, reflect.TypeOf(i))
 	}

+ 23 - 0
odf_test.go

@@ -9,6 +9,8 @@ import (
 	"odf/model"
 	_ "odf/model/stub"
 	"odf/xmlns"
+	"odf/xmlns/fo"
+	"odf/xmlns/table"
 	"os"
 	"testing"
 )
@@ -136,3 +138,24 @@ func TestDraw(t *testing.T) {
 	generators.GeneratePackage(m, embed, output, fm.MimeType)
 	assert.For(output.Close() == nil, 20)
 }
+
+func TestTableStyles(t *testing.T) {
+	output, _ := os.OpenFile("test-table-styles.odf", os.O_CREATE|os.O_WRONLY, 0666)
+	m := model.ModelFactory()
+	fm := &mappers.Formatter{}
+	fm.ConnectTo(m)
+	fm.MimeType = xmlns.MimeText
+	fm.Init()
+
+	fm.SetAttr(new(attr.TableAttributes).BorderModel(table.BorderModelCollapsing).AlignCenter().Width(10.0))
+	fm.SetAttr(new(attr.TableRowAttributes).UseOptimalRowHeight()).SetAttr(new(attr.TableColumnAttributes).UseOptimalColumnWidth())
+	fm.SetAttr(new(attr.TableCellAttributes).Border(attr.Border{Width: 0.01, Color: color.Black, Style: fo.Solid}))
+	tm := &mappers.TableMapper{}
+	tm.ConnectTo(fm)
+	tm.Write("test", 5, 10)
+	tt := tm.List["test"]
+	tm.Pos(tt, 0, 0).WriteString("Hello!")
+
+	generators.GeneratePackage(m, nil, output, fm.MimeType)
+	assert.For(output.Close() == nil, 20)
+}

+ 21 - 6
xmlns/fo/f.go

@@ -6,12 +6,16 @@ import (
 )
 
 const (
-	FontSize    model.AttrName = "fo:font-size"
-	TextAlign   model.AttrName = "fo:text-align"
-	BreakBefore model.AttrName = "fo:break-before"
-	Color       model.AttrName = "fo:color"
-	FontWeight  model.AttrName = "fo:font-weight"
-	FontStyle   model.AttrName = "fo:font-style"
+	FontSize     model.AttrName = "fo:font-size"
+	TextAlign    model.AttrName = "fo:text-align"
+	BreakBefore  model.AttrName = "fo:break-before"
+	Color        model.AttrName = "fo:color"
+	FontWeight   model.AttrName = "fo:font-weight"
+	FontStyle    model.AttrName = "fo:font-style"
+	BorderRight  model.AttrName = "fo:border-right"
+	BorderLeft   model.AttrName = "fo:border-left"
+	BorderTop    model.AttrName = "fo:border-top"
+	BorderBottom model.AttrName = "fo:border-bottom"
 )
 
 const (
@@ -29,6 +33,17 @@ const (
 	Justify = "justify"
 )
 
+const (
+	None       = "none"
+	Solid      = "solid"
+	Dotted     = "dotted"
+	Dash       = "dash"
+	LongDash   = "long-dash"
+	DotDash    = "dot-dash"
+	DotDotDash = "dot-dot-dash"
+	Wave       = "wave"
+)
+
 func init() {
 	xmlns.Typed[FontSize] = xmlns.INT
 	xmlns.Typed[TextAlign] = xmlns.ENUM

+ 27 - 11
xmlns/style/s.go

@@ -6,25 +6,41 @@ import (
 )
 
 const (
-	Style               model.LeafName = "style:style"
-	TextProperties      model.LeafName = "style:text-properties"
-	ParagraphProperties model.LeafName = "style:paragraph-properties"
-	DefaultStyle        model.LeafName = "style:default-style"
-	FontFace            model.LeafName = "style:font-face"
+	Style model.LeafName = "style:style"
+
+	TextProperties        model.LeafName = "style:text-properties"
+	TableProperties       model.LeafName = "style:table-properties"
+	ParagraphProperties   model.LeafName = "style:paragraph-properties"
+	TableRowProperties    model.LeafName = "style:table-row-properties"
+	TableColumnProperties model.LeafName = "style:table-column-properties"
+	TableCellProperties   model.LeafName = "style:table-cell-properties"
+
+	DefaultStyle model.LeafName = "style:default-style"
+	FontFace     model.LeafName = "style:font-face"
 )
 
 const (
-	Family   model.AttrName = "style:family"
-	Name     model.AttrName = "style:name"
-	FontName model.AttrName = "style:font-name"
+	Family                model.AttrName = "style:family"
+	Name                  model.AttrName = "style:name"
+	FontName              model.AttrName = "style:font-name"
+	Width                 model.AttrName = "style:width"
+	UseOptimalRowHeight   model.AttrName = "style:use-optimal-row-height"
+	UseOptimalColumnWidth model.AttrName = "style:use-optimal-column-width"
 )
 
 const (
-	FamilyText      = "text"
-	FamilyParagraph = "paragraph"
+	FamilyText        = "text"
+	FamilyParagraph   = "paragraph"
+	FamilyTable       = "table"
+	FamilyTableRow    = "table-row"
+	FamilyTableColumn = "table-column"
+	FamilyTableCell   = "table-cell"
 )
 
 func init() {
 	xmlns.Typed[Family] = xmlns.ENUM
-	xmlns.Enums[Family] = []string{FamilyText, FamilyParagraph}
+	xmlns.Enums[Family] = []string{FamilyText, FamilyParagraph, FamilyTable, FamilyTableRow, FamilyTableColumn, FamilyTableCell}
+	xmlns.Typed[Width] = xmlns.MEASURE
+	xmlns.Typed[UseOptimalColumnWidth] = xmlns.BOOL
+	xmlns.Typed[UseOptimalRowHeight] = xmlns.BOOL
 }

+ 15 - 0
xmlns/table/t.go

@@ -16,9 +16,24 @@ const (
 	Name                 model.AttrName = "table:name"
 	NumberColumnsSpanned                = "table:number-columns-spanned"
 	NumberRowsSpanned                   = "table:number-rows-spanned"
+	BorderModel                         = "table:border-model"
+	StyleName                           = "table:style-name"
+	Align                               = "table:align"
+)
+
+const (
+	BorderModelCollapsing = "collapsing"
+	BorderModelSeparating = "separating"
+	AlignLeft             = "left"
+	AlignRight            = "right"
+	AlignCenter           = "center"
 )
 
 func init() {
 	xmlns.Typed[NumberColumnsSpanned] = xmlns.INT
 	xmlns.Typed[NumberRowsSpanned] = xmlns.INT
+	xmlns.Typed[BorderModel] = xmlns.ENUM
+	xmlns.Enums[BorderModel] = []string{BorderModelCollapsing, BorderModelSeparating}
+	xmlns.Typed[Align] = xmlns.ENUM
+	xmlns.Enums[Align] = []string{AlignCenter, AlignLeft, AlignRight}
 }

+ 1 - 0
xmlns/x.go

@@ -46,6 +46,7 @@ const (
 	MEASURE
 	ENUM
 	COLOR
+	BOOL
 )
 
 type Mime string