ソースを参照

gui table dev

leonsal 8 年 前
コミット
a0311bdd0a
1 ファイル変更188 行追加32 行削除
  1. 188 32
      gui/table.go

+ 188 - 32
gui/table.go

@@ -18,9 +18,12 @@ type Table struct {
 	styles       *TableStyles            // pointer to current styles
 	cols         []TableColumn           // array of columns descriptors
 	colmap       map[string]*TableColumn // maps column id to column descriptor
-	firstRow     int                     // index of the first row of data to show
+	firstRow     int                     // index of the first visible row
+	lastRow      int                     // index of the last visible row
 	rows         []*tableRow             // array of table rows
-	headerHeight float32
+	headerHeight float32                 // header height
+	vscroll      *ScrollBar              // vertical scroll bar
+	showHeader   bool
 }
 
 // TableColumn describes a table column
@@ -86,6 +89,7 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 	t := new(Table)
 	t.Panel.Initialize(width, height)
 	t.styles = &StyleDefault.Table
+	t.showHeader = true
 
 	// Checks columns descriptors
 	t.colmap = make(map[string]*TableColumn)
@@ -129,33 +133,49 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 	return t, nil
 }
 
+// ShowHeaders shows or hides the table header
+func (t *Table) ShowHeader(show bool) {
+
+	if t.showHeader == show {
+		return
+	}
+	t.showHeader = show
+	for i := 0; i < len(t.cols); i++ {
+		c := &t.cols[i]
+		c.header.SetVisible(t.showHeader)
+	}
+	t.recalc()
+}
+
+// Len returns the total number of rows of the table
+func (t *Table) Len() int {
+
+	return len(t.rows)
+}
+
 // SetRows clears all current rows of the table and
 // sets new rows from the specifying parameter.
 // Each row is a map keyed by the colum id.
 // The map value currently can be a string or any number type
 // If a row column is not found it is ignored
-func (t *Table) SetRows(rows []map[string]interface{}) {
-
-	// Create rows if necessary
-	if len(rows) > len(t.rows) {
-		count := len(rows) - len(t.rows)
-		for ri := 0; ri < count; ri++ {
-			trow := new(tableRow)
-			trow.cells = make([]*tableCell, 0)
-			for ci := 0; ci < len(t.cols); ci++ {
-				cell := new(tableCell)
-				cell.Initialize(0, 0)
-				cell.label.initialize("", StyleDefault.Font)
-				cell.Add(&cell.label)
-				trow.cells = append(trow.cells, cell)
-				t.Panel.Add(cell)
-			}
-			t.rows = append(t.rows, trow)
+func (t *Table) SetRows(values []map[string]interface{}) {
+
+	// Add missing rows
+	if len(values) > len(t.rows) {
+		count := len(values) - len(t.rows)
+		for row := 0; row < count; row++ {
+			t.insertRow(len(t.rows), nil)
+		}
+		// Remove remaining rows
+	} else if len(values) < len(t.rows) {
+		for row := len(values); row < len(t.rows); row++ {
+			t.removeRow(row)
 		}
 	}
 
-	for ri := 0; ri < len(rows); ri++ {
-		t.SetRow(ri, rows[ri])
+	// Set rows values
+	for row := 0; row < len(values); row++ {
+		t.SetRow(row, values[row])
 	}
 	t.firstRow = 0
 	t.recalc()
@@ -204,8 +224,87 @@ func (t *Table) SetColFormat(id, format string) error {
 	return nil
 }
 
+// InsertRow inserts the specified values in a new row at the specified index
+func (t *Table) InsertRow(row int, values map[string]interface{}) {
+
+	t.insertRow(row, values)
+	t.recalc()
+}
+
+// RemoveRow removes from the specified row from the table
+func (t *Table) RemoveRow(row int) {
+
+	t.removeRow(row)
+	t.recalc()
+}
+
+// insertRow is the internal version of InsertRow which does not call recalc()
+func (t *Table) insertRow(row int, values map[string]interface{}) {
+
+	// Checks row index
+	if row < 0 || row > len(t.rows) {
+		panic("Invalid row index")
+	}
+
+	// Creates tableRow
+	trow := new(tableRow)
+	trow.cells = make([]*tableCell, 0)
+	for ci := 0; ci < len(t.cols); ci++ {
+		cell := new(tableCell)
+		cell.Initialize(0, 0)
+		cell.label.initialize("", StyleDefault.Font)
+		cell.Add(&cell.label)
+		trow.cells = append(trow.cells, cell)
+		t.Panel.Add(cell)
+	}
+
+	// Inserts tableRow in the table rows at the specified index
+	t.rows = append(t.rows, nil)
+	copy(t.rows[row+1:], t.rows[row:])
+	t.rows[row] = trow
+
+	// Sets the new row values from the specified map
+	if values != nil {
+		t.SetRow(row, values)
+	}
+}
+
+// removeRow removes from the table the row specified its index
+func (t *Table) removeRow(row int) {
+
+	// Checks row index
+	if row < 0 || row >= len(t.rows) {
+		panic("Invalid row index")
+	}
+
+	// Get row to be removed
+	trow := t.rows[row]
+
+	// Remove row from table
+	copy(t.rows[row:], t.rows[row+1:])
+	t.rows[len(t.rows)-1] = nil
+	t.rows = t.rows[:len(t.rows)-1]
+
+	// Dispose the row cell panels and its children
+	for i := 0; i < len(trow.cells); i++ {
+		cell := trow.cells[i]
+		cell.DisposeChildren(true)
+		cell.Dispose()
+	}
+
+	// Adjusts table first visible row if necessary
+	//if t.firstRow == row {
+	//	t.firstRow--
+	//	if t.firstRow < 0 {
+	//		t.firstRow = 0
+	//	}
+	//}
+}
+
+// AddRow adds a new row at the end of the table with the specified values
 func (t *Table) AddRow(values map[string]interface{}) {
 
+	t.InsertRow(len(t.rows), values)
 }
 
 // recalcHeader recalculates and sets the position and size of the header panels
@@ -231,12 +330,20 @@ func (t *Table) recalcHeader() {
 // - horizontal or vertical scroll position changed
 func (t *Table) recalc() {
 
-	// Assumes that the TableColum array is sorted in show order
-	py := t.headerHeight
+	// Get initial Y coordinate and total height of the table
+	starty := t.headerHeight
+	if !t.showHeader {
+		starty = 0
+	}
+	theight := t.ContentHeight()
+
+	// Calculates all visible rows heights and determines if it
+	// is necessary to show the scrollbar or not.
+	scroll := false
+	py := starty
 	for ri := t.firstRow; ri < len(t.rows); ri++ {
-		row := t.rows[ri]
+		trow := t.rows[ri]
 		t.updateRowStyle(ri)
-		px := float32(0)
 		// Get maximum height for row
 		for ci := 0; ci < len(t.cols); ci++ {
 			// If column is hidden, ignore
@@ -244,12 +351,28 @@ func (t *Table) recalc() {
 			if c.Hidden {
 				continue
 			}
-			cell := row.cells[c.order]
+			cell := trow.cells[c.order]
 			cellHeight := cell.MinHeight() + cell.label.Height()
-			if cellHeight > row.height {
-				row.height = cellHeight
+			if cellHeight > trow.height {
+				trow.height = cellHeight
 			}
 		}
+		py += trow.height
+		log.Error("row:%v py:%v row height:%v theight:%v", ri, py, trow.height, theight)
+		if py > theight {
+			scroll = true
+			t.lastRow = ri
+			break
+		}
+	}
+	t.setVScrollBar(scroll)
+
+	// Assumes that the TableColum array is sorted in show order
+	py = starty
+	for ri := t.firstRow; ri < len(t.rows); ri++ {
+		trow := t.rows[ri]
+		t.updateRowStyle(ri)
+		px := float32(0)
 		// Sets position and size of row cells
 		for ci := 0; ci < len(t.cols); ci++ {
 			// If column is hidden, ignore
@@ -258,14 +381,14 @@ func (t *Table) recalc() {
 				continue
 			}
 			// Sets cell position and size
-			cell := row.cells[c.order]
+			cell := trow.cells[c.order]
 			cell.SetPosition(px, py)
-			cell.SetSize(c.header.Width(), row.height)
+			cell.SetSize(c.header.Width(), trow.height)
 			//log.Error("Cell(%v,%v)(%p) size:%v/%v pos:%v/%v", ri, c.Id, &cell, cell.Width(), cell.Height(), cell.Position().X, cell.Position().Y)
 			px += c.header.Width()
 		}
-		py += row.height
-		if py > t.Height() {
+		py += trow.height
+		if py > theight {
 			break
 		}
 	}
@@ -275,6 +398,39 @@ func (t *Table) sortCols() {
 
 }
 
+// setVScrollBar sets the visibility state of the vertical scrollbar
+func (t *Table) setVScrollBar(state bool) {
+
+	// Visible
+	if state {
+		var scrollWidth float32 = 20
+		// Creates scroll bar if necessary
+		if t.vscroll == nil {
+			t.vscroll = NewVScrollBar(0, 0)
+			t.vscroll.SetBorders(0, 0, 0, 1)
+			//t.vscroll.Subscribe(OnChange, s.onScrollBarEvent)
+			t.Panel.Add(t.vscroll)
+		}
+		// Initial y coordinate and height
+		py := float32(0)
+		height := t.ContentHeight()
+		if t.showHeader {
+			py = t.headerHeight
+			height -= py
+		}
+		t.vscroll.SetSize(scrollWidth, height)
+		t.vscroll.SetPositionX(t.ContentWidth() - scrollWidth)
+		t.vscroll.SetPositionY(py)
+		t.vscroll.recalc()
+		t.vscroll.SetVisible(true)
+		// Not visible
+	} else {
+		if t.vscroll != nil {
+			t.vscroll.SetVisible(false)
+		}
+	}
+}
+
 // updateRowStyle applies the correct style for the specified row
 func (t *Table) updateRowStyle(ri int) {