Finished Image implementation.

This commit is contained in:
Oliver 2022-12-26 21:55:31 +01:00
parent 10a525d206
commit c5b1a7d818
9 changed files with 176 additions and 17 deletions

View File

@ -9,12 +9,13 @@ This Go package provides commonly used components for terminal based user interf
Among these components are: Among these components are:
- __Input forms__ (include __input/password fields__, __drop-down selections__, __checkboxes__, and __buttons__) - __Input forms__ (including __text input__, __selections__, __checkboxes__, and __buttons__)
- Navigable multi-color __text views__ - Navigable multi-color __text views__
- Editable multi-line __text areas__ - Editable multi-line __text areas__
- Sophisticated navigable __table views__ - Sophisticated navigable __table views__
- Flexible __tree views__ - Flexible __tree views__
- Selectable __lists__ - Selectable __lists__
- __Images__
- __Grid__, __Flexbox__ and __page layouts__ - __Grid__, __Flexbox__ and __page layouts__
- Modal __message windows__ - Modal __message windows__
- An __application__ wrapper - An __application__ wrapper

1
demos/image/README.md Normal file
View File

@ -0,0 +1 @@
![Screenshot](screenshot.jpg)

87
demos/image/main.go Normal file

File diff suppressed because one or more lines are too long

BIN
demos/image/screenshot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

19
form.go
View File

@ -1,6 +1,8 @@
package tview package tview
import ( import (
"image"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
@ -110,7 +112,7 @@ func NewForm() *Form {
fieldTextColor: Styles.PrimaryTextColor, fieldTextColor: Styles.PrimaryTextColor,
buttonStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor), buttonStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
buttonActivatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.ContrastBackgroundColor), buttonActivatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.ContrastBackgroundColor),
lastFinishedKey: -1, lastFinishedKey: tcell.KeyTab, // To skip over inactive elements at the beginning of the form.
} }
return f return f
@ -307,6 +309,21 @@ func (f *Form) AddCheckbox(label string, checked bool, changed func(checked bool
return f return f
} }
// AddImage adds an image to the form. It has a label and the image will fit in
// the specified width and height (its aspect ratio is preserved). See
// [Image.SetColors] for a description of the "colors" parameter. Images are not
// interactive and are skipped over in a form. The "width" value may be 0
// (adjust dynamically) but "height" should generally be a positive value.
func (f *Form) AddImage(label string, image image.Image, width, height, colors int) *Form {
f.items = append(f.items, NewImage().
SetLabel(label).
SetImage(image).
SetSize(height, width).
SetAlign(AlignTop, AlignLeft).
SetColors(colors))
return f
}
// AddButton adds a new button to the form. The "selected" function is called // AddButton adds a new button to the form. The "selected" function is called
// when the user selects this button. It may be nil. // when the user selects this button. It may be nil.
func (f *Form) AddButton(label string, selected func()) *Form { func (f *Form) AddButton(label string, selected func()) *Form {

View File

@ -79,9 +79,6 @@ type Image struct {
// "ImageDithering". // "ImageDithering".
dithering int dithering int
// The background color to use (RGB) for transparent pixels.
backgroundColor [3]int8
// The width of a terminal's cell divided by its height. // The width of a terminal's cell divided by its height.
aspectRatio float64 aspectRatio float64
@ -104,6 +101,10 @@ type Image struct {
// The actual image (in cells) when it was drawn the last time. The size of // The actual image (in cells) when it was drawn the last time. The size of
// this slice is lastWidth * lastHeight, indexed by y*lastWidth + x. // this slice is lastWidth * lastHeight, indexed by y*lastWidth + x.
pixels []pixel pixels []pixel
// A callback function set by the Form class and called when the user leaves
// this form item.
finished func(tcell.Key)
} }
// NewImage returns a new image widget with an empty image (use [SetImage] to // NewImage returns a new image widget with an empty image (use [SetImage] to
@ -173,21 +174,13 @@ func (i *Image) GetColors() int {
// SetDithering sets the dithering algorithm to use, one of the constants // SetDithering sets the dithering algorithm to use, one of the constants
// starting with "Dithering", for example [DitheringFloydSteinberg] (the // starting with "Dithering", for example [DitheringFloydSteinberg] (the
// default). // default). Dithering is not applied when rendering in true-color.
func (i *Image) SetDithering(dithering int) *Image { func (i *Image) SetDithering(dithering int) *Image {
i.dithering = dithering i.dithering = dithering
i.lastWidth, i.lastHeight = 0, 0 i.lastWidth, i.lastHeight = 0, 0
return i return i
} }
// SetBackgroundColor sets the background color to use (RGB) for transparent
// pixels in the original image. The default is black (0, 0, 0).
func (i *Image) SetBackgroundColor(r, g, b int8) *Image {
i.backgroundColor = [3]int8{r, g, b}
i.lastWidth, i.lastHeight = 0, 0
return i
}
// SetAspectRatio sets the width of a terminal's cell divided by its height. // SetAspectRatio sets the width of a terminal's cell divided by its height.
// You may change the default of 0.5 if your terminal uses a different aspect // You may change the default of 0.5 if your terminal uses a different aspect
// ratio. This is used to calculate the size of the image if one of the sizes // ratio. This is used to calculate the size of the image if one of the sizes
@ -229,6 +222,40 @@ func (i *Image) SetLabelWidth(width int) *Image {
return i return i
} }
// GetFieldWidth returns this primitive's field width. This is the image's width
// or, if the width is 0 or less, the proportional width of the image based on
// its height as returned by [Image.GetFieldHeight]. If there is no image, 0 is
// returned.
func (i *Image) GetFieldWidth() int {
if i.width <= 0 {
if i.image == nil {
return 0
}
bounds := i.image.Bounds()
height := i.GetFieldHeight()
return bounds.Dx() * height / bounds.Dy()
}
return i.width
}
// GetFieldHeight returns this primitive's field height. This is the image's
// height or 8 if the height is 0 or less.
func (i *Image) GetFieldHeight() int {
if i.height <= 0 {
return 8
}
return i.height
}
// SetFormAttributes sets attributes shared by all form items.
func (i *Image) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
i.labelWidth = labelWidth
i.backgroundColor = bgColor
i.SetLabelStyle(tcell.StyleDefault.Foreground(labelColor).Background(bgColor))
i.lastWidth, i.lastHeight = 0, 0
return i
}
// SetLabelStyle sets the style of the label. // SetLabelStyle sets the style of the label.
func (i *Image) SetLabelStyle(style tcell.Style) *Image { func (i *Image) SetLabelStyle(style tcell.Style) *Image {
i.labelStyle = style i.labelStyle = style
@ -240,6 +267,22 @@ func (i *Image) GetLabelStyle() tcell.Style {
return i.labelStyle return i.labelStyle
} }
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
func (i *Image) SetFinishedFunc(handler func(key tcell.Key)) FormItem {
i.finished = handler
return i
}
// Focus is called when this primitive receives focus.
func (i *Image) Focus(delegate func(p Primitive)) {
// If we're part of a form, there's nothing the user can do here so we're
// finished.
if i.finished != nil {
i.finished(-1)
return
}
}
// render re-populates the [Image.pixels] slice besed on the current settings, // render re-populates the [Image.pixels] slice besed on the current settings,
// if [Image.lastWidth] and [Image.lastHeight] don't match the current image's // if [Image.lastWidth] and [Image.lastHeight] don't match the current image's
// size. It also sets the new image size in these two variables. // size. It also sets the new image size in these two variables.

View File

@ -76,7 +76,7 @@ type List struct {
done func() done func()
} }
// NewList returns a new form. // NewList returns a new list.
func NewList() *List { func NewList() *List {
return &List{ return &List{
Box: NewBox(), Box: NewBox(),

BIN
tview.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 991 KiB

After

Width:  |  Height:  |  Size: 951 KiB