table.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package mappers
  2. import (
  3. "github.com/kpmy/odf/mappers/attr"
  4. "github.com/kpmy/odf/model"
  5. "github.com/kpmy/odf/xmlns/table"
  6. "github.com/kpmy/ypk/assert"
  7. )
  8. //Table structure holds the table structure and identifies it for TableMapper
  9. type Table struct {
  10. Rows int
  11. Columns int
  12. Root model.Leaf
  13. rowCache, colsCache []model.Leaf
  14. cellCache [][]model.Leaf
  15. }
  16. //TableMapper writes and manages tables in document model
  17. type TableMapper struct {
  18. List map[string]*Table
  19. fm *Formatter
  20. }
  21. //Ready or not
  22. func (t *TableMapper) Ready() bool {
  23. return t.fm != nil && t.fm.ready
  24. }
  25. func (t *TableMapper) newWriter(old ...model.Writer) model.Writer {
  26. return t.fm.m.NewWriter(old...)
  27. }
  28. //ConnectTo any valid Formatter and it's document model
  29. func (t *TableMapper) ConnectTo(fm *Formatter) {
  30. t.fm = fm
  31. t.List = make(map[string]*Table)
  32. }
  33. //Write a Table with given name and dimensions, table object is stored internally and can be accessed by name, latest set TableAttributes, TableRowAttributes, TableColumnAttributes and TableCellAttributes are used
  34. func (t *TableMapper) Write(name string, rows, cols int) {
  35. assert.For(t.Ready(), 20)
  36. assert.For(name != "" && t.List[name] == nil, 21)
  37. t.fm.attr.Flush()
  38. this := &Table{Rows: rows, Columns: cols}
  39. t.List[name] = this
  40. wr := t.newWriter()
  41. wr.Pos(t.fm.root)
  42. this.Root = wr.WritePos(New(table.Table))
  43. wr.Attr(table.Name, name)
  44. t.fm.attr.Fit(table.Table, func(a attr.Attributes) {
  45. wr.Attr(table.StyleName, a.Name())
  46. })
  47. for i := 0; i < this.Columns; i++ {
  48. col := New(table.TableColumn)
  49. this.colsCache = append(this.colsCache, col)
  50. this.cellCache = append(this.cellCache, make([]model.Leaf, 0))
  51. wr.Write(col)
  52. cwr := t.newWriter(wr)
  53. cwr.Pos(col)
  54. t.fm.attr.Fit(table.TableColumn, func(a attr.Attributes) {
  55. cwr.Attr(table.StyleName, a.Name())
  56. })
  57. }
  58. for i := 0; i < this.Rows; i++ {
  59. rwr := t.newWriter(wr)
  60. row := rwr.WritePos(New(table.TableRow))
  61. t.fm.attr.Fit(table.TableRow, func(a attr.Attributes) {
  62. rwr.Attr(table.StyleName, a.Name())
  63. })
  64. this.rowCache = append(this.rowCache, row)
  65. for j := 0; j < this.Columns; j++ {
  66. cell := New(table.TableCell)
  67. this.cellCache[j] = append(this.cellCache[j], cell)
  68. rwr.Write(cell)
  69. cwr := t.newWriter(rwr)
  70. cwr.Pos(cell)
  71. t.fm.attr.Fit(table.TableCell, func(a attr.Attributes) {
  72. cwr.Attr(table.StyleName, a.Name())
  73. })
  74. }
  75. }
  76. }
  77. //WriteRows to existing table latest set TableRowAttributes and TableCellAttributes are used
  78. func (t *TableMapper) WriteRows(this *Table, rows int) {
  79. assert.For(t.Ready(), 20)
  80. t.fm.attr.Flush()
  81. wr := t.newWriter()
  82. for i := 0; i < rows; i++ {
  83. wr.Pos(this.Root)
  84. row := wr.WritePos(New(table.TableRow))
  85. t.fm.attr.Fit(table.TableRow, func(a attr.Attributes) {
  86. wr.Attr(table.StyleName, a.Name())
  87. })
  88. this.rowCache = append(this.rowCache, row)
  89. for j := 0; j < this.Columns; j++ {
  90. cell := New(table.TableCell)
  91. this.cellCache[j] = append(this.cellCache[j], cell)
  92. wr.Write(cell)
  93. cwr := t.newWriter(wr)
  94. cwr.Pos(cell)
  95. t.fm.attr.Fit(table.TableCell, func(a attr.Attributes) {
  96. cwr.Attr(table.StyleName, a.Name())
  97. })
  98. }
  99. this.Rows++
  100. }
  101. }
  102. //WriteColumns to existing table latest set TableColumnAttributes and TableCellAttributes are used
  103. func (t *TableMapper) WriteColumns(this *Table, cols int) {
  104. assert.For(t.Ready(), 20)
  105. t.fm.attr.Flush()
  106. wr := t.newWriter()
  107. var last model.Leaf
  108. if this.Columns > 0 {
  109. last = this.colsCache[this.Columns-1]
  110. }
  111. for i := 0; i < cols; i++ {
  112. wr.Pos(this.Root)
  113. col := wr.WritePos(New(table.TableColumn), last)
  114. t.fm.attr.Fit(table.TableColumn, func(a attr.Attributes) {
  115. wr.Attr(table.StyleName, a.Name())
  116. })
  117. this.colsCache = append(this.colsCache, col)
  118. this.cellCache = append(this.cellCache, make([]model.Leaf, 0))
  119. this.Columns++
  120. for j := 0; j < this.Rows; j++ {
  121. t.WriteCells(this, j, 1)
  122. }
  123. }
  124. }
  125. //Write cells to existing table latest set TableCellAttributes are used
  126. func (t *TableMapper) WriteCells(this *Table, _row int, cells int) {
  127. assert.For(t.Ready(), 20)
  128. t.fm.attr.Flush()
  129. wr := t.newWriter()
  130. row := this.rowCache[_row]
  131. wr.Pos(row)
  132. for i := 0; i < cells; i++ {
  133. cell := New(table.TableCell)
  134. this.cellCache[i] = append(this.cellCache[i], cell)
  135. wr.Write(cell)
  136. cwr := t.newWriter(wr)
  137. cwr.Pos(cell)
  138. t.fm.attr.Fit(table.TableCell, func(a attr.Attributes) {
  139. cwr.Attr(table.StyleName, a.Name())
  140. })
  141. }
  142. }
  143. //Span merges visually
  144. func (t *TableMapper) Span(this *Table, row, col int, rowspan, colspan int) {
  145. assert.For(t.Ready(), 20)
  146. assert.For(rowspan > 0, 21)
  147. assert.For(colspan > 0, 22)
  148. wr := t.newWriter()
  149. wr.Pos(this.cellCache[col][row])
  150. wr.Attr(table.NumberRowsSpanned, rowspan)
  151. wr.Attr(table.NumberColumnsSpanned, colspan)
  152. }
  153. //Pos sets mapper to the cell with given coordinates
  154. func (t *TableMapper) Pos(this *Table, row, col int) *ParaMapper {
  155. ret := new(ParaMapper)
  156. ret.ConnectTo(t.fm)
  157. ret.rider.Pos(this.cellCache[col][row])
  158. return ret
  159. }