User can now select table cells
This commit is contained in:
		
							parent
							
								
									ebefcb03b3
								
							
						
					
					
						commit
						b357768c36
					
				| @ -2,6 +2,7 @@ package containers | |||||||
| 
 | 
 | ||||||
| import "image" | import "image" | ||||||
| import "git.tebibyte.media/sashakoshka/tomo" | import "git.tebibyte.media/sashakoshka/tomo" | ||||||
|  | import "git.tebibyte.media/sashakoshka/tomo/input" | ||||||
| import "git.tebibyte.media/sashakoshka/tomo/canvas" | import "git.tebibyte.media/sashakoshka/tomo/canvas" | ||||||
| import "git.tebibyte.media/sashakoshka/tomo/artist" | import "git.tebibyte.media/sashakoshka/tomo/artist" | ||||||
| import "git.tebibyte.media/sashakoshka/tomo/elements/core" | import "git.tebibyte.media/sashakoshka/tomo/elements/core" | ||||||
| @ -10,7 +11,7 @@ import "git.tebibyte.media/sashakoshka/tomo/default/config" | |||||||
| 
 | 
 | ||||||
| type tableCell struct { | type tableCell struct { | ||||||
| 	tomo.Element | 	tomo.Element | ||||||
| 	artist.Pattern | 	tomo.Pattern | ||||||
| 	image.Rectangle | 	image.Rectangle | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -35,9 +36,13 @@ type TableContainer struct { | |||||||
| 	forcedMinimumWidth  int | 	forcedMinimumWidth  int | ||||||
| 	forcedMinimumHeight int | 	forcedMinimumHeight int | ||||||
| 
 | 
 | ||||||
|  | 	selectedColumn int | ||||||
|  | 	selectedRow int | ||||||
|  | 	 | ||||||
| 	config config.Wrapped | 	config config.Wrapped | ||||||
| 	theme  theme.Wrapped | 	theme  theme.Wrapped | ||||||
| 
 | 
 | ||||||
|  | 	onSelect func () | ||||||
| 	onScrollBoundsChange func () | 	onScrollBoundsChange func () | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -50,6 +55,8 @@ func NewTableContainer ( | |||||||
| 	element = &TableContainer { | 	element = &TableContainer { | ||||||
| 		topHeading:     topHeading, | 		topHeading:     topHeading, | ||||||
| 		leftHeading:    leftHeading, | 		leftHeading:    leftHeading, | ||||||
|  | 		selectedColumn: -1, | ||||||
|  | 		selectedRow:    -1, | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	element.theme.Case = tomo.C("tomo", "tableContainer") | 	element.theme.Case = tomo.C("tomo", "tableContainer") | ||||||
| @ -153,6 +160,17 @@ func (element *TableContainer) Resize (columns, rows int) { | |||||||
| 	element.redoAll() | 	element.redoAll() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Selected returns the column and row of the cell that is currently selected. | ||||||
|  | // If no cell is selected, this method will return (-1, -1). | ||||||
|  | func (element *TableContainer) Selected () (column, row int) { | ||||||
|  | 	return element.selectedColumn, element.selectedRow | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // OnSelect sets a function to be called when the user selects a table cell. | ||||||
|  | func (element *TableContainer) OnSelect (callback func ()) { | ||||||
|  | 	element.onSelect = callback | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Warp runs the specified callback, deferring all layout and rendering updates | // Warp runs the specified callback, deferring all layout and rendering updates | ||||||
| // until the callback has finished executing. This allows for aplications to | // until the callback has finished executing. This allows for aplications to | ||||||
| // perform batch gui updates without flickering and stuff. | // perform batch gui updates without flickering and stuff. | ||||||
| @ -212,14 +230,42 @@ func (element *TableContainer) NotifyMinimumSizeChange (child tomo.Element) { | |||||||
| func (element *TableContainer) DrawBackground (bounds image.Rectangle) { | func (element *TableContainer) DrawBackground (bounds image.Rectangle) { | ||||||
| 	if !bounds.Overlaps(element.core.Bounds()) { return } | 	if !bounds.Overlaps(element.core.Bounds()) { return } | ||||||
| 	 | 	 | ||||||
| 	for _, row   := range element.grid { | 	for rowIndex,    row   := range element.grid { | ||||||
| 	for _, child := range row { | 	for columnIndex, child := range row { | ||||||
| 	if bounds.Overlaps(child.Rectangle) { | 	if bounds.Overlaps(child.Rectangle) { | ||||||
| 		child.Draw(canvas.Cut(element.core, bounds), child.Rectangle) | 		element.theme.Pattern ( | ||||||
|  | 			child.Pattern, | ||||||
|  | 			element.state(columnIndex, rowIndex)). | ||||||
|  | 			Draw(canvas.Cut(element.core, bounds), child.Rectangle) | ||||||
| 		return | 		return | ||||||
| 	}}} | 	}}} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (element *TableContainer) HandleMouseDown (x, y int, button input.Button) { | ||||||
|  | 	element.Propagator.HandleMouseDown(x, y, button) | ||||||
|  | 	if button != input.ButtonLeft { return } | ||||||
|  | 	 | ||||||
|  | 	for rowIndex,    row   := range element.grid { | ||||||
|  | 	for columnIndex, child := range row { | ||||||
|  | 	if image.Pt(x, y).In(child.Rectangle) { | ||||||
|  | 		selected := | ||||||
|  | 			rowIndex == element.selectedRow && | ||||||
|  | 			columnIndex == element.selectedColumn | ||||||
|  | 		if selected { return } | ||||||
|  | 		oldColumn, oldRow := element.selectedColumn, element.selectedRow | ||||||
|  | 		element.selectedColumn, element.selectedRow = columnIndex, rowIndex | ||||||
|  | 		if oldColumn >= 0 && oldRow >= 0 { | ||||||
|  | 			element.core.DamageRegion(element.redoCell(oldColumn, oldRow)) | ||||||
|  | 		} | ||||||
|  | 		element.core.DamageRegion(element.redoCell(columnIndex, rowIndex)) | ||||||
|  | 		if element.onSelect != nil { | ||||||
|  | 			element.onSelect() | ||||||
|  | 		} | ||||||
|  | 		return | ||||||
|  | 	}}} | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (element *TableContainer) hook (child tomo.Element) { | func (element *TableContainer) hook (child tomo.Element) { | ||||||
| 	if child0, ok := child.(tomo.Themeable); ok { | 	if child0, ok := child.(tomo.Themeable); ok { | ||||||
| 		child0.SetTheme(element.theme.Theme) | 		child0.SetTheme(element.theme.Theme) | ||||||
| @ -245,6 +291,36 @@ func (element *TableContainer) rebuildChildList (list []tomo.Element) { | |||||||
| 	}} | 	}} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (element *TableContainer) state (column, row int) (state tomo.State) { | ||||||
|  | 	if column == element.selectedColumn && row == element.selectedRow { | ||||||
|  | 		state.On = true | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (element *TableContainer) redoCell (column, row int) image.Rectangle { | ||||||
|  | 	padding := element.theme.Padding(tomo.PatternTableCell) | ||||||
|  | 	cell := element.grid[row][column] | ||||||
|  | 	pattern := element.theme.Pattern ( | ||||||
|  | 		cell.Pattern, element.state(column, row)) | ||||||
|  | 		 | ||||||
|  | 	if cell.Element != nil { | ||||||
|  | 		// give child canvas portion | ||||||
|  | 		innerCellBounds := padding.Apply(cell.Rectangle) | ||||||
|  | 		artist.DrawShatter ( | ||||||
|  | 			element.core, pattern, | ||||||
|  | 			cell.Rectangle, innerCellBounds) | ||||||
|  | 		cell.DrawTo ( | ||||||
|  | 			canvas.Cut(element.core, innerCellBounds), | ||||||
|  | 			innerCellBounds, | ||||||
|  | 			element.childDrawCallback) | ||||||
|  | 	} else { | ||||||
|  | 		// draw cell pattern in empty cells | ||||||
|  | 		pattern.Draw(element.core, cell.Rectangle) | ||||||
|  | 	} | ||||||
|  | 	return cell.Rectangle | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (element *TableContainer) redoAll () { | func (element *TableContainer) redoAll () { | ||||||
| 	if element.warping || !element.core.HasImage() { | 	if element.warping || !element.core.HasImage() { | ||||||
| 		element.updateMinimumSize() | 		element.updateMinimumSize() | ||||||
| @ -294,7 +370,7 @@ func (element *TableContainer) redoAll () { | |||||||
| 	x := float64(bounds.Min.X) | 	x := float64(bounds.Min.X) | ||||||
| 	y := float64(bounds.Min.Y) | 	y := float64(bounds.Min.Y) | ||||||
| 	for rowIndex, row := range element.grid { | 	for rowIndex, row := range element.grid { | ||||||
| 		for columnIndex, child := range row { | 		for columnIndex, _ := range row { | ||||||
| 			width  := columnWidths[columnIndex] | 			width  := columnWidths[columnIndex] | ||||||
| 			height := rowHeights[rowIndex] | 			height := rowHeights[rowIndex] | ||||||
| 			cellBounds := image.Rect ( | 			cellBounds := image.Rect ( | ||||||
| @ -310,26 +386,10 @@ func (element *TableContainer) redoAll () { | |||||||
| 			} else { | 			} else { | ||||||
| 				id = tomo.PatternTableCell | 				id = tomo.PatternTableCell | ||||||
| 			} | 			} | ||||||
| 			pattern := element.theme.Pattern(id, tomo.State { }) |  | ||||||
| 			element.grid[rowIndex][columnIndex].Rectangle = cellBounds | 			element.grid[rowIndex][columnIndex].Rectangle = cellBounds | ||||||
| 			element.grid[rowIndex][columnIndex].Pattern = pattern | 			element.grid[rowIndex][columnIndex].Pattern   = id | ||||||
| 			 | 			 | ||||||
| 			if child.Element != nil { | 			element.redoCell(columnIndex, rowIndex) | ||||||
| 				// give child canvas portion |  | ||||||
| 				innerCellBounds := padding.Apply(cellBounds) |  | ||||||
| 				artist.DrawShatter ( |  | ||||||
| 					element.core, pattern, |  | ||||||
| 					cellBounds, innerCellBounds) |  | ||||||
| 				child.DrawTo ( |  | ||||||
| 					canvas.Cut(element.core, innerCellBounds), |  | ||||||
| 					innerCellBounds, |  | ||||||
| 					func (region image.Rectangle) { |  | ||||||
| 						element.core.DamageRegion(region) |  | ||||||
| 					}) |  | ||||||
| 			} else { |  | ||||||
| 				// draw cell pattern in empty cells |  | ||||||
| 				pattern.Draw(element.core, cellBounds) |  | ||||||
| 			} |  | ||||||
| 			x += float64(width) | 			x += float64(width) | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| @ -371,3 +431,7 @@ func (element *TableContainer) updateMinimumSize () { | |||||||
| 
 | 
 | ||||||
| 	element.core.SetMinimumSize(minWidth, minHeight) | 	element.core.SetMinimumSize(minWidth, minHeight) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (element *TableContainer) childDrawCallback (region image.Rectangle) { | ||||||
|  | 	element.core.DamageRegion(region) | ||||||
|  | } | ||||||
|  | |||||||
| @ -29,10 +29,18 @@ func run () { | |||||||
| 		} | 		} | ||||||
| 		index ++ | 		index ++ | ||||||
| 	}} | 	}} | ||||||
| 
 |  | ||||||
| 	table.Set(2, 1, elements.NewButton("Look, I'm a button!")) | 	table.Set(2, 1, elements.NewButton("Look, I'm a button!")) | ||||||
| 
 | 
 | ||||||
|  | 	statusLabel := elements.NewLabel("Selected: none", false) | ||||||
|  | 	table.OnSelect (func () { | ||||||
|  | 		column, row := table.Selected() | ||||||
|  | 		statusLabel.SetText ( | ||||||
|  | 			fmt.Sprintf("Selected: %d, %d", | ||||||
|  | 			column, row)) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
| 	container.Adopt(table, true) | 	container.Adopt(table, true) | ||||||
|  | 	container.Adopt(statusLabel, false) | ||||||
| 	window.Adopt(container) | 	window.Adopt(container) | ||||||
| 	 | 	 | ||||||
| 	window.OnClose(tomo.Stop) | 	window.OnClose(tomo.Stop) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user