| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package gui
- type GridLayout struct {
- columns int
- }
- type GridLayoutParams struct {
- Row int // grid layout row number from 0
- Col int // grid layout column number from 0
- ColSpan int // number of additional columns to ocuppy to the right
- AlignH Align // vertical alignment
- AlignV Align // horizontal alignment
- }
- // NewGridLayout creates and returns a pointer of a new grid layout
- func NewGridLayout() *GridLayout {
- g := new(GridLayout)
- return g
- }
- func (g *GridLayout) Recalc(ipan IPanel) {
- type element struct {
- panel *Panel
- params *GridLayoutParams
- }
- rows := 0
- cols := 0
- items := []element{}
- pan := ipan.GetPanel()
- for _, obj := range pan.Children() {
- // Get child panel
- child := obj.(IPanel).GetPanel()
- // Ignore if not visible
- if !child.Visible() {
- continue
- }
- // Ignore if no layout params
- if child.layoutParams == nil {
- continue
- }
- // Checks layout params
- params, ok := child.layoutParams.(*GridLayoutParams)
- if !ok {
- panic("layoutParams is not GridLayoutParams")
- }
- if params.Row >= rows {
- rows = params.Row + 1
- }
- if params.Col >= cols {
- cols = params.Col + 1
- }
- items = append(items, element{child, params})
- }
- // Check limits
- if rows > 100 {
- panic("Element row outsize limits")
- }
- if cols > 100 {
- panic("Element column outsize limits")
- }
- // Determine row and column maximum sizes
- colSizes := make([]int, cols)
- rowSizes := make([]int, rows)
- for _, el := range items {
- width := el.panel.Width()
- height := el.panel.Height()
- if int(width) > colSizes[el.params.Col] {
- colSizes[el.params.Col] = int(width)
- }
- if int(height) > rowSizes[el.params.Row] {
- rowSizes[el.params.Row] = int(height)
- }
- }
- // Determine row and column starting positions
- colStart := make([]int, cols)
- rowStart := make([]int, rows)
- for i := 1; i < len(colSizes); i++ {
- colStart[i] = colStart[i-1] + colSizes[i-1]
- }
- for i := 1; i < len(rowSizes); i++ {
- rowStart[i] = rowStart[i-1] + rowSizes[i-1]
- }
- // Position the elements
- for _, el := range items {
- row := el.params.Row
- col := el.params.Col
- cellHeight := rowSizes[row]
- // Current cell width
- cellWidth := 0
- for c := 0; c <= el.params.ColSpan; c++ {
- pos := col + c
- if pos >= len(colSizes) {
- break
- }
- cellWidth += colSizes[pos]
- }
- rstart := float32(rowStart[row])
- cstart := float32(colStart[col])
- // Horizontal alignment
- var dx float32 = 0
- switch el.params.AlignH {
- case AlignNone:
- case AlignLeft:
- case AlignRight:
- dx = float32(cellWidth) - el.panel.width
- case AlignCenter:
- dx = (float32(cellWidth) - el.panel.width) / 2
- default:
- panic("Invalid horizontal alignment")
- }
- // Vertical alignment
- var dy float32 = 0
- switch el.params.AlignV {
- case AlignNone:
- case AlignTop:
- case AlignBottom:
- dy = float32(cellHeight) - el.panel.height
- case AlignCenter:
- dy = (float32(cellHeight) - el.panel.height) / 2
- default:
- panic("Invalid vertical alignment")
- }
- el.panel.SetPosition(cstart+dx, rstart+dy)
- }
- }
|