github.com/wrgl/wrgl@v0.14.0/pkg/widgets/merge_row.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright © 2022 Wrangle Ltd
     3  
     4  package widgets
     5  
     6  import (
     7  	"github.com/gdamore/tcell/v2"
     8  	"github.com/wrgl/wrgl/pkg/diff"
     9  	"github.com/wrgl/wrgl/pkg/merge"
    10  )
    11  
    12  var (
    13  	resolvedCell   = NewTableCell("resolved").SetStyle(boldGreenStyle)
    14  	unresolvedCell = NewTableCell("unresolved").SetStyle(boldStyle)
    15  )
    16  
    17  type MergeRow struct {
    18  	cd      *diff.ColDiff
    19  	Cells   [][]*TableCell
    20  	baseRow []string
    21  	buf     *diff.BlockBuffer
    22  }
    23  
    24  func NewMergeRow(buf *diff.BlockBuffer, cd *diff.ColDiff, names []string) *MergeRow {
    25  	l := cd.Layers() + 1
    26  	n := cd.Len() + 1
    27  	numPK := len(cd.OtherPK[0])
    28  	c := &MergeRow{
    29  		buf:   buf,
    30  		cd:    cd,
    31  		Cells: make([][]*TableCell, l),
    32  	}
    33  	for i := 0; i < l; i++ {
    34  		c.Cells[i] = make([]*TableCell, n)
    35  		for j := 0; j < n; j++ {
    36  			c.Cells[i][j] = NewTableCell("")
    37  			if j == 0 && i < l-1 {
    38  				c.Cells[i][j].SetText(names[i]).SetStyle(boldStyle)
    39  			} else if j < numPK+1 {
    40  				c.Cells[i][j].SetStyle(primaryKeyStyle)
    41  			} else {
    42  				c.Cells[i][j].SetStyle(cellStyle)
    43  			}
    44  		}
    45  	}
    46  	return c
    47  }
    48  
    49  func (c *MergeRow) DisplayMerge(m *merge.Merge) error {
    50  	baseInd := len(c.Cells) - 1
    51  	if m.Resolved {
    52  		c.Cells[baseInd][0] = resolvedCell
    53  	} else {
    54  		c.Cells[baseInd][0] = unresolvedCell
    55  	}
    56  	if m.Base != nil {
    57  		c.baseRow = make([]string, c.cd.Len())
    58  		blk, off := diff.RowToBlockAndOffset(m.BaseOffset)
    59  		row, err := c.buf.GetRow(0, blk, off)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		row = c.cd.RearrangeBaseRow(row)
    64  		for i, s := range row {
    65  			c.baseRow[i] = s
    66  		}
    67  	} else {
    68  		c.baseRow = nil
    69  	}
    70  	numPK := len(c.cd.OtherPK[0])
    71  	for i, sum := range m.Others {
    72  		cell := c.Cells[i][0]
    73  		if sum == nil {
    74  			cell.SetStyle(boldRedStyle)
    75  			for j := 0; j < c.cd.Len(); j++ {
    76  				cell := c.Cells[i][j+1]
    77  				cell.SetText("")
    78  				if j >= numPK {
    79  					cell.SetStyle(cellStyle)
    80  				}
    81  			}
    82  			continue
    83  		} else if m.Base == nil {
    84  			cell.SetStyle(boldGreenStyle)
    85  		} else if string(sum) == string(m.Base) {
    86  			cell.SetStyle(boldStyle)
    87  		} else {
    88  			cell.SetStyle(boldYellowStyle)
    89  		}
    90  
    91  		blk, off := diff.RowToBlockAndOffset(m.OtherOffsets[i])
    92  		row, err := c.buf.GetRow(byte(i+1), blk, off)
    93  		if err != nil {
    94  			return err
    95  		}
    96  		row = c.cd.RearrangeRow(i, row)
    97  		for j, s := range row {
    98  			cell := c.Cells[i][j+1]
    99  			cell.SetText(s)
   100  			if j >= len(c.cd.OtherPK[0]) {
   101  				if c.baseRow == nil {
   102  					cell.SetStyle(greenStyle)
   103  				} else {
   104  					baseTxt := c.baseRow[j]
   105  					if _, ok := c.cd.Removed[i][uint32(j)]; ok {
   106  						cell.SetStyle(redStyle)
   107  					} else if _, ok := c.cd.Added[i][uint32(j)]; ok {
   108  						cell.SetStyle(greenStyle)
   109  					} else if baseTxt != cell.Text {
   110  						cell.SetStyle(yellowStyle)
   111  					} else {
   112  						cell.SetStyle(cellStyle)
   113  					}
   114  				}
   115  			}
   116  		}
   117  	}
   118  	if m.ResolvedRow != nil {
   119  		for i, s := range m.ResolvedRow {
   120  			_, ok := m.UnresolvedCols[uint32(i)]
   121  			if m.Resolved {
   122  				ok = false
   123  			}
   124  			c.SetCell(i, s, ok)
   125  		}
   126  	} else if c.baseRow != nil {
   127  		for i, s := range c.baseRow {
   128  			c.SetCell(i, s, !m.Resolved)
   129  		}
   130  	}
   131  	return nil
   132  }
   133  
   134  func (c *MergeRow) SetCell(col int, s string, unresolved bool) {
   135  	cell := c.Cells[c.cd.Layers()][col+1]
   136  	cell.SetText(s)
   137  	for i, m := range c.cd.Added {
   138  		if _, ok := m[uint32(col)]; ok && c.Cells[i][col+1].Text == s {
   139  			cell.SetStyle(greenStyle)
   140  			return
   141  		}
   142  	}
   143  	if col < len(c.cd.OtherPK[0]) {
   144  		cell.SetStyle(primaryKeyStyle)
   145  		return
   146  	} else if c.baseRow == nil {
   147  		cell.SetStyle(greenStyle)
   148  	} else if s != c.baseRow[col] {
   149  		cell.SetStyle(yellowStyle)
   150  	} else {
   151  		cell.SetStyle(cellStyle)
   152  	}
   153  	if unresolved {
   154  		cell.SetBackgroundColor(tcell.ColorDarkRed).DisableTransparency(true)
   155  	} else {
   156  		cell.SetBackgroundColor(tcell.ColorBlack).DisableTransparency(false).SetTransparency(true)
   157  	}
   158  }
   159  
   160  type MergeRowPool struct {
   161  	blkBuf *diff.BlockBuffer
   162  	cd     *diff.ColDiff
   163  	names  []string
   164  	buf    []*MergeRow
   165  	rowMap map[int]int
   166  	merges []*merge.Merge
   167  	minInd int
   168  	maxInd int
   169  }
   170  
   171  func NewMergeRowPool(blkBuf *diff.BlockBuffer, cd *diff.ColDiff, names []string, merges []*merge.Merge) *MergeRowPool {
   172  	return &MergeRowPool{
   173  		blkBuf: blkBuf,
   174  		cd:     cd,
   175  		names:  names,
   176  		merges: merges,
   177  		rowMap: map[int]int{},
   178  	}
   179  }
   180  
   181  func (p *MergeRowPool) rowFromBuf(ind int) (*MergeRow, error) {
   182  	n := len(p.buf)
   183  	if c := cap(p.buf); n >= c {
   184  		p.buf = append(p.buf, nil)
   185  	} else {
   186  		p.buf = p.buf[:n+1]
   187  	}
   188  	if p.buf[n] == nil {
   189  		p.buf[n] = NewMergeRow(p.blkBuf, p.cd, p.names)
   190  	}
   191  	err := p.buf[n].DisplayMerge(p.merges[ind])
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	if ind > p.maxInd {
   196  		p.maxInd = ind
   197  	} else if ind < p.minInd {
   198  		p.minInd = ind
   199  	}
   200  	p.rowMap[ind] = n
   201  	return p.buf[n], nil
   202  }
   203  
   204  func (p *MergeRowPool) getRow(ind int) (*MergeRow, error) {
   205  	if ind < 0 || ind > len(p.merges) {
   206  		return nil, nil
   207  	}
   208  	if v, ok := p.rowMap[ind]; ok {
   209  		return p.buf[v], nil
   210  	}
   211  	if ind < p.minInd-200 || ind > p.maxInd+200 {
   212  		p.rowMap = map[int]int{}
   213  		p.buf = p.buf[:0]
   214  		p.minInd = ind
   215  		p.maxInd = ind
   216  	}
   217  	return p.rowFromBuf(ind)
   218  }
   219  
   220  func (p *MergeRowPool) SetCell(row, col int, s string, unresolved bool) {
   221  	r, err := p.getRow(row)
   222  	if err != nil {
   223  		panic(err)
   224  	}
   225  	r.SetCell(col, s, unresolved)
   226  }
   227  
   228  func (p *MergeRowPool) IsTextAtCellDifferentFromBase(row, col, layer int) bool {
   229  	r, err := p.getRow(row)
   230  	if err != nil {
   231  		panic(err)
   232  	}
   233  	return r.Cells[layer][col].Text != r.Cells[p.cd.Layers()][col].Text
   234  }
   235  
   236  func (p *MergeRowPool) GetCell(row, col, subrow int) *TableCell {
   237  	r, err := p.getRow(row)
   238  	if err != nil {
   239  		panic(err)
   240  	}
   241  	return r.Cells[subrow][col]
   242  }
   243  
   244  func (p *MergeRowPool) RefreshRow(row int) {
   245  	r, err := p.getRow(row)
   246  	if err != nil {
   247  		return
   248  	}
   249  	r.DisplayMerge(p.merges[row])
   250  }