leonsal 8 лет назад
Родитель
Сommit
2eb06c8a83
2 измененных файлов с 148 добавлено и 25 удалено
  1. 24 2
      gui/style.go
  2. 124 23
      gui/table.go

+ 24 - 2
gui/style.go

@@ -753,12 +753,28 @@ func setupDefaultStyle() {
 			BgColor:     math32.Color{0.7, 0.7, 0.7},
 			FgColor:     fgColor,
 		},
-		Row: &TableRowStyles{
+		RowEven: &TableRowStyles{
 			Normal: TableRowStyle{
 				Border:      BorderSizes{0, 1, 1, 0},
 				Paddings:    BorderSizes{2, 2, 2, 2},
 				BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
-				BgColor:     bgColor,
+				BgColor:     math32.Color{0.85, 0.85, 0.85},
+				FgColor:     fgColor,
+			},
+			Selected: TableRowStyle{
+				Border:      BorderSizes{0, 1, 1, 0},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
+				BgColor:     math32.Color{0.7, 0.7, 0.7},
+				FgColor:     fgColor,
+			},
+		},
+		RowOdd: &TableRowStyles{
+			Normal: TableRowStyle{
+				Border:      BorderSizes{0, 1, 1, 0},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
+				BgColor:     math32.Color{0.82, 0.82, 0.82},
 				FgColor:     fgColor,
 			},
 			Selected: TableRowStyle{
@@ -776,5 +792,11 @@ func setupDefaultStyle() {
 			BgColor:     math32.Color{0.9, 0.9, 0.9},
 			FgColor:     fgColor,
 		},
+		Resizer: &TableResizerStyle{
+			Width:       4,
+			Border:      BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     math32.Color4{0.4, 0.4, 0.4, 0.6},
+		},
 	}
 }

+ 124 - 23
gui/table.go

@@ -59,7 +59,9 @@ type Table struct {
 	statusPanel    Panel        // optional bottom status panel
 	statusLabel    *Label       // status label
 	scrollBarEvent bool         // do not update the scrollbar value in recalc() if true
+	resizerPanel   Panel        // resizer panel
 	resizeCol      int          // column being resized
+	resizerX       float32      // initial resizer x coordinate
 	resizing       bool         // draggin the column resizer
 }
 
@@ -113,7 +115,7 @@ type TableRowStyles struct {
 	Selected TableRowStyle
 }
 
-// TableStatusStyle describes the style of the table status lineow
+// TableStatusStyle describes the style of the table status line panel
 type TableStatusStyle struct {
 	Border      BorderSizes
 	Paddings    BorderSizes
@@ -122,11 +124,21 @@ type TableStatusStyle struct {
 	FgColor     math32.Color
 }
 
+// TableResizerStyle describes the style of the table resizer panel
+type TableResizerStyle struct {
+	Width       float32
+	Border      BorderSizes
+	BorderColor math32.Color4
+	BgColor     math32.Color4
+}
+
 // TableStyles describes all styles of the table header and rows
 type TableStyles struct {
-	Header *TableHeaderStyle
-	Row    *TableRowStyles
-	Status *TableStatusStyle
+	Header  *TableHeaderStyle
+	RowEven *TableRowStyles
+	RowOdd  *TableRowStyles
+	Status  *TableStatusStyle
+	Resizer *TableResizerStyle
 }
 
 // TableClickEvent describes a mouse click event over a table
@@ -163,6 +175,7 @@ type tableColHeader struct {
 	resize     bool            // column can be resized by user
 	order      int             // row columns order
 	sorted     int             // current sorted status
+	xl         float32         // left border coordinate in pixels
 	xr         float32         // right border coordinate in pixels
 }
 
@@ -246,6 +259,12 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 	t.Panel.Add(&t.header)
 	t.recalcHeader()
 
+	// Creates resizer panel
+	t.resizerPanel.Initialize(t.styles.Resizer.Width, 0)
+	t.resizerPanel.SetVisible(false)
+	t.applyResizerStyle()
+	t.Panel.Add(&t.resizerPanel)
+
 	// Creates status panel
 	t.statusPanel.Initialize(0, 0)
 	t.statusPanel.SetVisible(false)
@@ -268,6 +287,13 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 	return t, nil
 }
 
+// SetStyles set this table styles overriding the default
+func (t *Table) SetStyles(ts *TableStyles) {
+
+	t.styles = ts
+	t.recalc()
+}
+
 // ShowHeader shows or hides the table header
 func (t *Table) ShowHeader(show bool) {
 
@@ -402,12 +428,12 @@ func (t *Table) SetColFormat(id, format string) error {
 // SetColOrder sets the exhibition order of the specified column.
 // The previous column which has the specified order will have
 // the original column order.
-func (t *Table) SetColOrder(id string, order int) {
+func (t *Table) SetColOrder(colid string, order int) {
 
 	// Checks column id
-	c := t.header.cmap[id]
+	c := t.header.cmap[colid]
 	if c == nil {
-		panic(fmt.Sprintf("No column with id:%s", id))
+		panic(fmt.Sprintf("No column with id:%s", colid))
 	}
 	// Checks exhibition order
 	if order < 0 || order > len(t.header.cols) {
@@ -436,6 +462,44 @@ func (t *Table) SetColOrder(id string, order int) {
 	t.recalc()
 }
 
+// EnableColResize enable or disables if the specified column can be resized by the
+// user using the mouse.
+func (t *Table) EnableColResize(colid string, enable bool) {
+
+	// Checks column id
+	c := t.header.cmap[colid]
+	if c == nil {
+		panic(fmt.Sprintf("No column with id:%s", colid))
+	}
+	c.resize = enable
+}
+
+// SetColWidth sets the specified column width and may
+// change the widths of the columns to the right
+func (t *Table) SetColWidth(colid string, width float32) {
+
+	// Checks column id
+	c := t.header.cmap[colid]
+	if c == nil {
+		panic(fmt.Sprintf("No column with id:%s", colid))
+	}
+	// Checks width minimum and maximuns
+	if width < 0 {
+		width = 16
+	}
+	if width > t.ContentHeight() {
+		width = t.ContentHeight()
+	}
+
+	c.SetWidth(width)
+	// Recalculates the header and all rows
+	t.recalcHeader()
+	for ri := 0; ri < len(t.rows); ri++ {
+		t.recalcRow(ri)
+	}
+	t.recalc()
+}
+
 // AddRow adds a new row at the end of the table with the specified values
 func (t *Table) AddRow(values map[string]interface{}) {
 
@@ -707,12 +771,13 @@ func (t *Table) onCursorPos(evname string, ev interface{}) {
 	kev := ev.(*window.CursorEvent)
 	cx, _ := t.ContentCoords(kev.Xpos, kev.Ypos)
 
-	// User is dragging the resizer
+	// If user is dragging the resizer, updates its position
 	if t.resizing {
+		t.resizerPanel.SetPosition(cx, 0)
 		return
 	}
 
-	// Find column with right border closest to current position
+	// Checks if the mouse cursor is near the border of a resizable column
 	found := false
 	for ci := 0; ci < len(t.header.cols); ci++ {
 		c := t.header.cols[ci]
@@ -721,13 +786,15 @@ func (t *Table) onCursorPos(evname string, ev interface{}) {
 			if c.resize {
 				found = true
 				t.resizeCol = ci
+				t.resizerX = c.xr
+				t.root.SetCursorHResize()
 			}
 			break
 		}
 	}
-	if found {
-		t.root.SetCursorHResize()
-	} else {
+	// If column not found but previously was near a resizable column,
+	// resets the the window cursor.
+	if !found && t.resizeCol >= 0 {
 		t.root.SetCursorNormal()
 		t.resizeCol = -1
 	}
@@ -741,9 +808,18 @@ func (t *Table) onMouse(evname string, ev interface{}) {
 	t.root.SetKeyFocus(t)
 	switch evname {
 	case OnMouseDown:
-		// If
+		// If over a resizable column border, shows the resizer panel
 		if t.resizeCol >= 0 {
 			t.resizing = true
+			height := t.ContentHeight()
+			if t.statusPanel.Visible() {
+				height -= t.statusPanel.Height()
+			}
+			px := t.resizerX - t.resizerPanel.Width()/2
+			t.resizerPanel.SetPositionX(px)
+			t.resizerPanel.SetHeight(height)
+			t.resizerPanel.SetVisible(true)
+			t.SetTopChild(&t.resizerPanel)
 			return
 		}
 		// Creates and dispatch TableClickEvent
@@ -757,9 +833,18 @@ func (t *Table) onMouse(evname string, ev interface{}) {
 			t.recalc()
 		}
 	case OnMouseUp:
+		// If user was resizing a column, hides the resizer and
+		// sets the new column width if possible
 		if t.resizing {
 			t.resizing = false
+			t.resizerPanel.SetVisible(false)
 			t.root.SetCursorNormal()
+			// Calculates the new column width
+			cx, _ := t.ContentCoords(e.Xpos, e.Ypos)
+			c := t.header.cols[t.resizeCol]
+			width := cx - c.xl
+			log.Error("width:%v", width)
+			t.SetColWidth(c.id, width)
 		}
 	default:
 		return
@@ -1025,6 +1110,7 @@ func (t *Table) recalcHeader() {
 		}
 		c.SetPosition(posx, 0)
 		c.SetVisible(true)
+		c.xl = posx
 		posx += c.Width()
 		c.xr = posx
 	}
@@ -1155,10 +1241,6 @@ func (t *Table) recalcRow(ri int) {
 	trow.SetContentWidth(px)
 }
 
-func (t *Table) sortCols() {
-
-}
-
 // rowsHeight returns the available start y coordinate and height in the table for rows,
 // considering the visibility of the header and status panels.
 func (t *Table) rowsHeight() (float32, float32) {
@@ -1265,11 +1347,21 @@ func (t *Table) calcMaxFirst() int {
 func (t *Table) updateRowStyle(ri int) {
 
 	row := t.rows[ri]
+	var trs *TableRowStyle
 	if row.selected {
-		t.applyRowStyle(row, &t.styles.Row.Selected)
-		return
+		if ri%2 == 0 {
+			trs = &t.styles.RowEven.Selected
+		} else {
+			trs = &t.styles.RowOdd.Selected
+		}
+	} else {
+		if ri%2 == 0 {
+			trs = &t.styles.RowEven.Normal
+		} else {
+			trs = &t.styles.RowOdd.Normal
+		}
 	}
-	t.applyRowStyle(row, &t.styles.Row.Normal)
+	t.applyRowStyle(row, trs)
 }
 
 // applyHeaderStyle applies style to the specified table header
@@ -1283,10 +1375,10 @@ func (t *Table) applyHeaderStyle(h *tableColHeader) {
 }
 
 // applyRowStyle applies the specified style to all cells for the specified table row
-func (t *Table) applyRowStyle(row *tableRow, trs *TableRowStyle) {
+func (t *Table) applyRowStyle(trow *tableRow, trs *TableRowStyle) {
 
-	for i := 0; i < len(row.cells); i++ {
-		cell := row.cells[i]
+	for i := 0; i < len(trow.cells); i++ {
+		cell := trow.cells[i]
 		cell.SetBordersFrom(&trs.Border)
 		cell.SetBordersColor4(&trs.BorderColor)
 		cell.SetPaddingsFrom(&trs.Paddings)
@@ -1304,6 +1396,15 @@ func (t *Table) applyStatusStyle() {
 	t.statusPanel.SetColor(&s.BgColor)
 }
 
+// applyResizerStyle applies the status style
+func (t *Table) applyResizerStyle() {
+
+	s := t.styles.Resizer
+	t.resizerPanel.SetBordersFrom(&s.Border)
+	t.resizerPanel.SetBordersColor4(&s.BorderColor)
+	t.resizerPanel.SetColor4(&s.BgColor)
+}
+
 // tableSortString is an internal type implementing the sort.Interface
 // and is used to sort a table column interpreting its values as strings
 type tableSortString struct {