Bläddra i källkod

gui table dev

leonsal 8 år sedan
förälder
incheckning
3adecfdab3
1 ändrade filer med 144 tillägg och 99 borttagningar
  1. 144 99
      gui/table.go

+ 144 - 99
gui/table.go

@@ -25,19 +25,15 @@ const (
 // organized in rows and columns.
 //
 type Table struct {
-	Panel                                // Embedded panel
-	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 visible row
-	lastRow      int                     // index of the last visible row
-	rows         []*tableRow             // array of table rows
-	headerHeight float32                 // header height
-	vscroll      *ScrollBar              // vertical scroll bar
-	showHeader   bool                    // header visibility flag
-	statusPanel  Panel                   // optional bottom status panel
-	statusLabel  *Label                  // status label
-
+	Panel                    // Embedded panel
+	styles      *TableStyles // pointer to current styles
+	header      tableHeader  // table headers
+	firstRow    int          // index of the first visible row
+	lastRow     int          // index of the last visible row
+	rows        []*tableRow  // array of table rows
+	vscroll     *ScrollBar   // vertical scroll bar
+	statusPanel Panel        // optional bottom status panel
+	statusLabel *Label       // status label
 }
 
 // TableColumn describes a table column
@@ -50,8 +46,6 @@ type TableColumn struct {
 	Alignment Align   // Cell content alignment: AlignNone|AlignLeft|AlignCenter|AlignRight
 	Expand    int     // Width expansion factor
 	order     int     // show order
-	header    *Panel  // header panel
-	label     *Label  // header label
 }
 
 // TableHeaderStyle describes the style of the table header
@@ -105,6 +99,25 @@ type TableClickEvent struct {
 	Col               string  // Id of table column (may be empty)
 }
 
+// tableHeader is panel which contains the individual header panels for each column
+type tableHeader struct {
+	Panel                            // embedded panel
+	cmap  map[string]*tableColHeader // maps column id with its panel/descriptor
+	cols  []*tableColHeader          // array of individual column headers/descriptors
+}
+
+// tableColHeader is panel for a column header
+type tableColHeader struct {
+	Panel          // header panel
+	label  *Label  // header label
+	id     string  // column id
+	width  float32 // initial column width
+	format string  // column format string
+	align  Align   // column alignment
+	expand int     // column expand factor
+	order  int     // row columns order
+}
+
 // tableRow is panel which contains an entire table row of cells
 type tableRow struct {
 	Panel                 // embedded panel
@@ -126,48 +139,78 @@ 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)
-	t.cols = make([]*TableColumn, 0)
-	for i := 0; i < len(cols); i++ {
-		// Make a copy of the column descriptor argument and saves its pointer
-		c := cols[i]
-		t.cols = append(t.cols, &c)
+
+	// Initialize table header
+	t.header.Initialize(0, 0)
+	t.header.cmap = make(map[string]*tableColHeader)
+	t.header.cols = make([]*tableColHeader, 0)
+
+	// Create column header panels
+	for ci := 0; ci < len(cols); ci++ {
+		cdesc := cols[ci]
 		// Column id must not be empty
-		if c.Id == "" {
+		if cdesc.Id == "" {
 			return nil, fmt.Errorf("Column with empty id")
 		}
 		// Column id must be unique
-		if t.colmap[c.Id] != nil {
+		if t.header.cmap[cdesc.Id] != nil {
 			return nil, fmt.Errorf("Column with duplicate id")
 		}
+		// Creates a column header
+		c := new(tableColHeader)
+		c.Initialize(0, 0)
+		t.applyHeaderStyle(c)
+		c.label = NewLabel(cdesc.Name)
+		c.Add(c.label)
+		c.id = cdesc.Id
+		c.width = cdesc.Width
+		c.align = cdesc.Alignment
+		c.format = cdesc.Format
+		c.expand = cdesc.Expand
 		// Sets default format and order
-		if c.Format == "" {
-			c.Format = "%v"
+		if c.format == "" {
+			c.format = "%v"
 		}
-		c.order = i
-		t.colmap[c.Id] = &c
-	}
-
-	// Create header panels
-	for i := 0; i < len(t.cols); i++ {
-		c := t.cols[i]
-		c.header = NewPanel(0, 0)
-		t.applyHeaderStyle(c.header)
-		c.label = NewLabel(c.Name)
-		c.header.Add(c.label)
-		width := c.Width
-		if width < c.label.Width()+c.header.MinWidth() {
-			width = c.label.Width() + c.header.MinWidth()
+		c.order = ci
+		c.SetVisible(!cdesc.Hidden)
+		t.header.cmap[c.id] = c
+		// Sets column header width and height
+		width := cdesc.Width
+		if width < c.label.Width()+c.MinWidth() {
+			width = c.label.Width() + c.MinWidth()
 		}
-		c.header.SetContentSize(width, c.label.Height())
-		t.headerHeight = c.header.Height()
-		t.Panel.Add(c.header)
+		c.SetContentSize(width, c.label.Height())
+		// Adds the column header to the header panel
+		t.header.cols = append(t.header.cols, c)
+		t.header.Panel.Add(c)
 	}
+	t.Panel.Add(&t.header)
 	t.recalcHeader()
 
+	//// Create column header panels
+	//t.header.Initialize(0, 0)
+	//t.header.cols = make([]*tableColHeader, 0)
+	//for i := 0; i < len(t.cols); i++ {
+	//	c := t.cols[i]
+	//	// Creates a column header
+	//	ch := new(tableColHeader)
+	//	ch.Initialize(0, 0)
+	//	ch.label = NewLabel(c.Name)
+	//	ch.Add(ch.label)
+	//	t.applyHeaderStyle(ch)
+	//	// Sets column header width and height
+	//	width := c.Width
+	//	if width < ch.label.Width()+ch.MinWidth() {
+	//		width = ch.label.Width() + ch.MinWidth()
+	//	}
+	//	ch.SetContentSize(width, ch.label.Height())
+	//	// Adds the column header to the header panel
+	//	t.header.cols = append(t.header.cols, ch)
+	//	t.header.Panel.Add(ch)
+	//}
+	//t.Panel.Add(&t.header)
+	//t.recalcHeader()
+
 	// Creates status panel
 	t.statusPanel.Initialize(0, 0)
 	t.statusPanel.SetVisible(false)
@@ -191,14 +234,10 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 // ShowHeader shows or hides the table header
 func (t *Table) ShowHeader(show bool) {
 
-	if t.showHeader == show {
+	if t.header.Visible() == show {
 		return
 	}
-	t.showHeader = show
-	for i := 0; i < len(t.cols); i++ {
-		c := t.cols[i]
-		c.header.SetVisible(t.showHeader)
-	}
+	t.header.SetVisible(show)
 	t.recalc()
 }
 
@@ -206,14 +245,14 @@ func (t *Table) ShowHeader(show bool) {
 // If the column id does not exit the function panics.
 func (t *Table) ShowColumn(col string, show bool) {
 
-	c := t.colmap[col]
+	c := t.header.cmap[col]
 	if c == nil {
 		panic("Invalid column id")
 	}
-	if c.Hidden == !show {
+	if c.Visible() == show {
 		return
 	}
-	c.Hidden = !show
+	c.SetVisible(show)
 	t.recalcHeader()
 	// Recalculates all rows
 	for ri := 0; ri < len(t.rows); ri++ {
@@ -227,10 +266,10 @@ func (t *Table) ShowColumn(col string, show bool) {
 func (t *Table) ShowAllColumns() {
 
 	recalc := false
-	for ci := 0; ci < len(t.cols); ci++ {
-		c := t.cols[ci]
-		if c.Hidden {
-			c.Hidden = false
+	for ci := 0; ci < len(t.header.cols); ci++ {
+		c := t.header.cols[ci]
+		if !c.Visible() {
+			c.SetVisible(true)
 			recalc = true
 		}
 	}
@@ -287,13 +326,13 @@ func (t *Table) SetRow(row int, values map[string]interface{}) {
 	if row < 0 || row >= len(t.rows) {
 		panic("Invalid row index")
 	}
-	for ci := 0; ci < len(t.cols); ci++ {
-		c := t.cols[ci]
-		cv := values[c.Id]
+	for ci := 0; ci < len(t.header.cols); ci++ {
+		c := t.header.cols[ci]
+		cv := values[c.id]
 		if cv == nil {
 			continue
 		}
-		t.SetCell(row, c.Id, values[c.Id])
+		t.SetCell(row, c.id, values[c.id])
 	}
 	t.recalcRow(t.rows[row])
 }
@@ -304,23 +343,23 @@ func (t *Table) SetCell(row int, colid string, value interface{}) {
 	if row < 0 || row >= len(t.rows) {
 		panic("Invalid row index")
 	}
-	c := t.colmap[colid]
+	c := t.header.cmap[colid]
 	if c == nil {
 		return
 	}
 	cell := t.rows[row].cells[c.order]
-	cell.label.SetText(fmt.Sprintf(c.Format, value))
+	cell.label.SetText(fmt.Sprintf(c.format, value))
 }
 
 // SetColFormat sets the formatting string (Printf) for the specified column
 // Update must be called to update the table.
 func (t *Table) SetColFormat(id, format string) error {
 
-	c := t.colmap[id]
+	c := t.header.cmap[id]
 	if c == nil {
 		return fmt.Errorf("No column with id:%s", id)
 	}
-	c.Format = format
+	c.format = format
 	return nil
 }
 
@@ -392,7 +431,7 @@ func (t *Table) insertRow(row int, values map[string]interface{}) {
 	trow := new(tableRow)
 	trow.Initialize(0, 0)
 	trow.cells = make([]*tableCell, 0)
-	for ci := 0; ci < len(t.cols); ci++ {
+	for ci := 0; ci < len(t.header.cols); ci++ {
 		// Creates tableRow cell panel
 		cell := new(tableCell)
 		cell.Initialize(0, 0)
@@ -539,14 +578,14 @@ func (t *Table) findClick(ev *TableClickEvent) {
 	ev.Row = -1
 	// Find column id
 	colx := float32(0)
-	for ci := 0; ci < len(t.cols); ci++ {
-		c := t.cols[ci]
-		if c.Hidden {
+	for ci := 0; ci < len(t.header.cols); ci++ {
+		c := t.header.cols[ci]
+		if !c.Visible() {
 			continue
 		}
-		colx += c.header.Width()
+		colx += t.header.cols[ci].Width()
 		if x < colx {
-			ev.Col = c.Id
+			ev.Col = c.id
 			break
 		}
 	}
@@ -555,14 +594,14 @@ func (t *Table) findClick(ev *TableClickEvent) {
 		return
 	}
 	// Checks if is in header
-	if t.showHeader && y < t.headerHeight {
+	if t.header.Visible() && y < t.header.Height() {
 		ev.Header = true
 	}
 
 	// Find row clicked
 	rowy := float32(0)
-	if t.showHeader {
-		rowy = t.headerHeight
+	if t.header.Visible() {
+		rowy = t.header.Height()
 	}
 	theight := t.ContentHeight()
 	for ri := t.firstRow; ri < len(t.rows); ri++ {
@@ -674,16 +713,20 @@ func (t *Table) selectRow(ri int) {
 func (t *Table) recalcHeader() {
 
 	posx := float32(0)
-	for i := 0; i < len(t.cols); i++ {
-		c := t.cols[i]
-		if c.Hidden {
-			c.header.SetVisible(false)
+	height := float32(0)
+	for ci := 0; ci < len(t.header.cols); ci++ {
+		c := t.header.cols[ci]
+		if !c.Visible() {
 			continue
 		}
-		c.header.SetPosition(posx, 0)
-		c.header.SetVisible(true)
-		posx += c.header.Width()
+		if c.Height() > height {
+			height = c.Height()
+		}
+		c.SetPosition(posx, 0)
+		c.SetVisible(true)
+		posx += c.Width()
 	}
+	t.header.SetContentSize(posx, height)
 }
 
 // recalcStatus recalculates and sets the position and size of the status panel and its label
@@ -753,10 +796,10 @@ func (t *Table) recalcRow(trow *tableRow) {
 
 	// Calculates and sets row height
 	maxheight := float32(0)
-	for ci := 0; ci < len(t.cols); ci++ {
+	for ci := 0; ci < len(t.header.cols); ci++ {
 		// If column is hidden, ignore
-		c := t.cols[ci]
-		if c.Hidden {
+		c := t.header.cols[ci]
+		if !c.Visible() {
 			continue
 		}
 		cell := trow.cells[c.order]
@@ -769,19 +812,21 @@ func (t *Table) recalcRow(trow *tableRow) {
 
 	// Sets row cells sizes and positions and sets row width
 	px := float32(0)
-	for ci := 0; ci < len(t.cols); ci++ {
+	for ci := 0; ci < len(t.header.cols); ci++ {
 		// If column is hidden, ignore
-		c := t.cols[ci]
+		c := t.header.cols[ci]
 		cell := trow.cells[c.order]
-		if c.Hidden {
+		if !c.Visible() {
 			cell.SetVisible(false)
 			continue
 		}
 		// Sets cell position and size
 		cell.SetPosition(px, 0)
 		cell.SetVisible(true)
-		cell.SetSize(c.header.Width(), trow.ContentHeight())
-		px += c.header.Width()
+		cell.SetSize(c.Width(), trow.ContentHeight())
+		// Sets the cell label position inside the cell
+
+		px += c.Width()
 	}
 	trow.SetContentWidth(px)
 }
@@ -796,9 +841,9 @@ func (t *Table) rowsHeight() (float32, float32) {
 
 	start := float32(0)
 	height := t.ContentHeight()
-	if t.showHeader {
-		height -= t.headerHeight
-		start += t.headerHeight
+	if t.header.Visible() {
+		height -= t.header.Height()
+		start += t.header.Height()
 	}
 	if t.statusPanel.Visible() {
 		height -= t.statusPanel.Height()
@@ -886,14 +931,14 @@ func (t *Table) updateRowStyle(ri int) {
 	t.applyRowStyle(row, &t.styles.Row.Normal)
 }
 
-// applyHeaderStyle applies the specified menu body style
-func (t *Table) applyHeaderStyle(hp *Panel) {
+// applyHeaderStyle applies style to the specified table header
+func (t *Table) applyHeaderStyle(h *tableColHeader) {
 
 	s := t.styles.Header
-	hp.SetBordersFrom(&s.Border)
-	hp.SetBordersColor4(&s.BorderColor)
-	hp.SetPaddingsFrom(&s.Paddings)
-	hp.SetColor(&s.BgColor)
+	h.SetBordersFrom(&s.Border)
+	h.SetBordersColor4(&s.BorderColor)
+	h.SetPaddingsFrom(&s.Paddings)
+	h.SetColor(&s.BgColor)
 }
 
 // applyRowStyle applies the specified style to all cells for the specified table row