Skip to content
This repository has been archived by the owner on Oct 13, 2021. It is now read-only.

ScrollArea does not expand to fit window size #130

Open
nick-kanakis opened this issue Apr 14, 2018 · 8 comments
Open

ScrollArea does not expand to fit window size #130

nick-kanakis opened this issue Apr 14, 2018 · 8 comments

Comments

@nick-kanakis
Copy link

The header is one line Table created like this:

header := tui.NewTable(0, 0) 
header.SetColumnStretch(0, 1)
header.SetColumnStretch(1, 4) 
header.SetColumnStretch(2, 4) 
header.SetColumnStretch(3, 4) 
labelID := tui.NewLabel("ID")
labelNT := tui.NewLabel("Notebook Title")
labelT := tui.NewLabel("Note Title")
labelTags := tui.NewLabel("Tags")

Under the header there is a table created similar to header:

notesInfoList := tui.NewTable(0, 0)
notesInfoList.SetColumnStretch(0, 1)
notesInfoList.SetColumnStretch(1, 4)
notesInfoList.SetColumnStretch(2, 4)
notesInfoList.SetColumnStretch(3, 4)
notesInfoList.SetFocused(true)

for _, note := range jNotes {
		notesInfoList.AppendRow(
			//Note ID
			tui.NewLabel(strconv.Itoa(int(note.ID))),
			//Notebook title
			tui.NewLabel(note.NotebookTitle),
			//Note title
			tui.NewLabel(note.Title),
			//Note tags
			tui.NewLabel(note.Tags),
		)
	}

Everthything is aligned until I put the notesInfoList in a ScrollArea, what I do is:

scrollNotesInfo := tui.NewScrollArea(notesInfoList)
root := tui.NewVBox(header, scrollNotesInfo, mainPart, footer)
ui, err := tui.New(root)
if err != nil {
	log.Fatal(err)
}

Then the scrollable area shrinks to the left

With scrollable :
example

Without scrollable :

example2

Any ideas why this is happening?

@lrstanley
Copy link
Contributor

Take a look at the documentation for SetSizePolicy and the widgets which implement it. You will likely need to set maximum, or similar, for widgets to stretch available space.

https://godoc.org/github.com/marcusolsson/tui-go#SizePolicy

@lrstanley
Copy link
Contributor

Also worth looking at some of the examples. The chat example utilizes size policies, to handle sizing. E.g. "this widget should take up as much space as possible", or "this widget should take up as little space as possible"

input := tui.NewEntry()
input.SetFocused(true)
input.SetSizePolicy(tui.Expanding, tui.Maximum)
inputBox := tui.NewHBox(input)
inputBox.SetBorder(true)
inputBox.SetSizePolicy(tui.Expanding, tui.Maximum)

@nick-kanakis
Copy link
Author

nick-kanakis commented Apr 15, 2018

I have tried both:
scrollNotesInfo.SetSizePolicy(tui.Preferred, tui.Maximum)
and
scrollNotesInfo.SetSizePolicy(tui.Preferred, tui.Expanding)
with no difference,

The full code:

func createUI(jNotes []*jsonNote) tui.UI {
	//Create header & footer
	header, footer := constructHeaderFooter()

	//Create list of notes to select from + make the list scrollable
	notesInfoList := constructNotesList(jNotes, created, lastUpdated, memo)
	scrollNotesInfo := tui.NewScrollArea(notesInfoList)
	scrollNotesInfo.SetSizePolicy(tui.Preferred, tui.Maximum)

	//Join everything together and run the UI
	root := tui.NewVBox(header, scrollNotesInfo, footer)
	ui, err := tui.New(root)
	if err != nil {
		log.Fatal(err)
	}
	return ui
}

func constructHeaderFooter() (*tui.Table, *tui.Label) {
	header := tui.NewTable(0, 0)
	header.SetColumnStretch(0, 1)
	header.SetColumnStretch(1, 4)
	header.SetColumnStretch(2, 4)
	header.SetColumnStretch(3, 4)
	//header.SetSizePolicy(tui.Maximum, tui.Minimum)

	labelID := tui.NewLabel("ID")
	labelNT := tui.NewLabel("Notebook Title")
	labelT := tui.NewLabel("Note Title")
	labelTags := tui.NewLabel("Tags")
	header.AppendRow(labelID, labelNT, labelT, labelTags)
	//unselect it
	header.Select(-1)

	footer := tui.NewLabel("Press 'Ctrl+U' to update a note, 'Ctrl+D' to delete it or 'Esc' to exit.")
	footer.SetStyleName("footer")

	return header, footer
}

func constructNotesList(jNotes []*jsonNote, created, lastUpdated, memo *tui.Label) *tui.Table {
	notesInfoList := tui.NewTable(0, 0)
	notesInfoList.SetColumnStretch(0, 1)
	notesInfoList.SetColumnStretch(1, 4)
	notesInfoList.SetColumnStretch(2, 4)
	notesInfoList.SetColumnStretch(3, 4)
	notesInfoList.SetFocused(true)

	for _, note := range jNotes {
		notesInfoList.AppendRow(
			//Note ID
			tui.NewLabel(strconv.Itoa(int(note.ID))),
			//Notebook title
			tui.NewLabel(note.NotebookTitle),
			//Note title
			tui.NewLabel(note.Title),
			//Note tags
			tui.NewLabel(strings.Join(note.Tags, ",")),

		)
	}
	notesInfoList.Select(0)
	return notesInfoList
}

@lrstanley
Copy link
Contributor

It's been a few since I've used tui-go, but if I recall correctly, you may need to change the size policy of the opposing element too (looks like in this case, the bordered "note" box you have). If the element doesn't have a SetSizePolicy, simply wrap it in a VBox or similar.

If you can't get it working, can you provide a complete runnable example? The code you have provided is missing quite a bit. Or at least a complete minimal version with the issues you're facing (with dummy data).

@lrstanley
Copy link
Contributor

May need to also set size policies on the inner element within the scroll area too, to ensure it maximizes the horizontal space.

@nick-kanakis
Copy link
Author

package main

import (
	"strconv"
	"github.com/marcusolsson/tui-go"
	"log"
)

func main(){
	//Header
	header := tui.NewTable(0, 0)
	header.SetColumnStretch(0, 1)
	header.SetColumnStretch(1, 4)
	header.SetColumnStretch(2, 4)
	header.SetColumnStretch(3, 4)

	column1 := tui.NewLabel("column1")
	column2 := tui.NewLabel("column2")
	column3 := tui.NewLabel("column3")
	column4 := tui.NewLabel("column4")
	header.AppendRow(column1, column2, column3, column4)
	//unselect it
	header.Select(-1)

	//List
	list := tui.NewTable(0, 0)
	list.SetColumnStretch(0, 2)
	list.SetColumnStretch(1, 4)
	list.SetColumnStretch(2, 4)
	list.SetColumnStretch(3, 4)
	list.SetFocused(true)

	for i :=0 ; i<10; i++{
		list.AppendRow(
			tui.NewLabel( strconv.Itoa(i)),
			tui.NewLabel("Column2 data: " + strconv.Itoa(i)),
			tui.NewLabel("Column3 data: " + strconv.Itoa(i)),
			tui.NewLabel("Column4 data: " + strconv.Itoa(i)),
		)
	}
	list.Select(0)
	list.SetSizePolicy(tui.Preferred, tui.Expanding)

	//Scroll Area
	scrollArea := tui.NewScrollArea(list)
	scrollArea.SetSizePolicy(tui.Preferred, tui.Expanding)

	//Footer
	footer := tui.NewLabel("This is just a footer.")

	root := tui.NewVBox(header, scrollArea, footer)
	ui, err := tui.New(root)
	if err != nil {
		log.Fatal(err)
	}

	//Esc
	ui.SetKeybinding("Esc", func() { ui.Quit() })

	//Up arrow
	ui.SetKeybinding("Up", func() {
		windowSize := scrollArea.SizeHint().Y
		index := list.Selected()
		if index > 0 {
		index := list.Selected()
		list.Select(index - 1)
			if 10 <= windowSize {
				return
			}
			if index > windowSize {
				scrollArea.Scroll(0, -1)
			} else {
				scrollArea.ScrollToTop()
			}
		}
	})

	//Down arrow
	ui.SetKeybinding("Down", func() {
		windowSize := scrollArea.SizeHint().Y
		index := list.Selected()
		if index < 9 {
			list.Select(index + 1)
			if 10 <= windowSize {
				return
			}
			if index < 10-windowSize {
				scrollArea.Scroll(0, 1)
			} else {
				scrollArea.ScrollToBottom()
			}
		}
	})
	
	if err := ui.Run(); err != nil {
		log.Fatal(err)
	}
}

I also set the size policy of the inner element, but no results. The dummy example above has the same issue.
Thanks lrstanley

@lrstanley
Copy link
Contributor

I've attempted to correct the issue with the example code, however I am unable. If I recall correctly, I may have ran into a similar issue in the past.

It's almost like the SizeHint() method isn't properly being taken from the inner widget, and/or table, even when set to Expanding or Maximum, still will not fill the space from within a ScrollArea, when there isn't a large enough widget in one of the rows. In the past, the only way I was able to resolve it, was by putting a widget in the table which actually fills the space.

Unfortunately, I'm not too familiar with the internals of tui-go, and how painting works. Maybe @marcusolsson has an idea?

@nick-kanakis
Copy link
Author

@lrstanley Your workaround (adding a second set of columns in the table with an empty label) seems to work. But I do not like this approach so I hope to find some time on the weekend to fix the underlying bug.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants