mirror of
https://github.com/mum4k/termdash.git
synced 2025-05-04 22:18:07 +08:00
Refactoring y.Details off the object.
This commit is contained in:
parent
9b3edb42b9
commit
feb406ec11
@ -88,19 +88,30 @@ func RequiredWidth(minVal, maxVal float64) int {
|
|||||||
}) + axisWidth
|
}) + axisWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
// Details retrieves details about the Y axis required to draw it on a canvas
|
// YProperties are the properties of the Y axis.
|
||||||
// of the provided area.
|
type YProperties struct {
|
||||||
// The argument reqXHeight is the height required for the X axis and its labels.
|
// Min is the minimum value on the axis.
|
||||||
func (y *Y) Details(cvsAr image.Rectangle, reqXHeight int, mode YScaleMode) (*YDetails, error) {
|
Min float64
|
||||||
|
// Max is the maximum value on the axis.
|
||||||
|
Max float64
|
||||||
|
// ReqXHeight is the height required for the X axis and its labels.
|
||||||
|
ReqXHeight int
|
||||||
|
// ScaleMode determines how the Y axis scales.
|
||||||
|
ScaleMode YScaleMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewYDetails retrieves details about the Y axis required to draw it on a
|
||||||
|
// canvas of the provided area.
|
||||||
|
func NewYDetails(cvsAr image.Rectangle, yp *YProperties) (*YDetails, error) {
|
||||||
cvsWidth := cvsAr.Dx()
|
cvsWidth := cvsAr.Dx()
|
||||||
cvsHeight := cvsAr.Dy()
|
cvsHeight := cvsAr.Dy()
|
||||||
maxWidth := cvsWidth - 1 // Reserve one column for the line chart itself.
|
maxWidth := cvsWidth - 1 // Reserve one column for the line chart itself.
|
||||||
if req := RequiredWidth(y.min.Value, y.max.Value); maxWidth < req {
|
if req := RequiredWidth(yp.Min, yp.Max); maxWidth < req {
|
||||||
return nil, fmt.Errorf("the available maxWidth %d is smaller than the reported required width %d", maxWidth, req)
|
return nil, fmt.Errorf("the available maxWidth %d is smaller than the reported required width %d", maxWidth, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
graphHeight := cvsHeight - reqXHeight
|
graphHeight := cvsHeight - yp.ReqXHeight
|
||||||
scale, err := NewYScale(y.min.Value, y.max.Value, graphHeight, nonZeroDecimals, mode)
|
scale, err := NewYScale(yp.Min, yp.Max, graphHeight, nonZeroDecimals, yp.ScaleMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -28,51 +28,55 @@ type updateY struct {
|
|||||||
|
|
||||||
func TestY(t *testing.T) {
|
func TestY(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
desc string
|
desc string
|
||||||
minVal float64
|
yp *YProperties
|
||||||
maxVal float64
|
cvsAr image.Rectangle
|
||||||
update *updateY
|
wantWidth int
|
||||||
reqXHeight int
|
want *YDetails
|
||||||
mode YScaleMode
|
wantErr bool
|
||||||
cvsAr image.Rectangle
|
|
||||||
wantWidth int
|
|
||||||
want *YDetails
|
|
||||||
wantErr bool
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "fails on canvas too small",
|
desc: "fails on canvas too small",
|
||||||
minVal: 0,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 0,
|
||||||
cvsAr: image.Rect(0, 0, 3, 2),
|
Max: 3,
|
||||||
reqXHeight: 2,
|
ReqXHeight: 2,
|
||||||
wantWidth: 2,
|
},
|
||||||
wantErr: true,
|
cvsAr: image.Rect(0, 0, 3, 2),
|
||||||
|
wantWidth: 2,
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "fails on cvsWidth less than required width",
|
desc: "fails on cvsWidth less than required width",
|
||||||
minVal: 0,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 0,
|
||||||
cvsAr: image.Rect(0, 0, 2, 4),
|
Max: 3,
|
||||||
reqXHeight: 2,
|
ReqXHeight: 2,
|
||||||
wantWidth: 2,
|
},
|
||||||
wantErr: true,
|
cvsAr: image.Rect(0, 0, 2, 4),
|
||||||
|
wantWidth: 2,
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "fails when max is less than min",
|
desc: "fails when max is less than min",
|
||||||
minVal: 0,
|
yp: &YProperties{
|
||||||
maxVal: -1,
|
Min: 0,
|
||||||
cvsAr: image.Rect(0, 0, 4, 4),
|
Max: -1,
|
||||||
reqXHeight: 2,
|
ReqXHeight: 2,
|
||||||
wantWidth: 3,
|
},
|
||||||
wantErr: true,
|
cvsAr: image.Rect(0, 0, 4, 4),
|
||||||
|
wantWidth: 3,
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "cvsWidth equals required width",
|
desc: "cvsWidth equals required width",
|
||||||
minVal: 0,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 0,
|
||||||
cvsAr: image.Rect(0, 0, 3, 4),
|
Max: 3,
|
||||||
wantWidth: 2,
|
ReqXHeight: 2,
|
||||||
reqXHeight: 2,
|
},
|
||||||
|
cvsAr: image.Rect(0, 0, 3, 4),
|
||||||
|
wantWidth: 2,
|
||||||
want: &YDetails{
|
want: &YDetails{
|
||||||
Width: 2,
|
Width: 2,
|
||||||
Start: image.Point{1, 0},
|
Start: image.Point{1, 0},
|
||||||
@ -85,13 +89,15 @@ func TestY(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "success for anchored scale",
|
desc: "success for anchored scale",
|
||||||
minVal: 1,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 1,
|
||||||
mode: YScaleModeAnchored,
|
Max: 3,
|
||||||
cvsAr: image.Rect(0, 0, 3, 4),
|
ReqXHeight: 2,
|
||||||
reqXHeight: 2,
|
ScaleMode: YScaleModeAnchored,
|
||||||
wantWidth: 2,
|
},
|
||||||
|
cvsAr: image.Rect(0, 0, 3, 4),
|
||||||
|
wantWidth: 2,
|
||||||
want: &YDetails{
|
want: &YDetails{
|
||||||
Width: 2,
|
Width: 2,
|
||||||
Start: image.Point{1, 0},
|
Start: image.Point{1, 0},
|
||||||
@ -104,13 +110,15 @@ func TestY(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "accommodates X scale that needs more height",
|
desc: "accommodates X scale that needs more height",
|
||||||
minVal: 1,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 1,
|
||||||
mode: YScaleModeAnchored,
|
Max: 3,
|
||||||
cvsAr: image.Rect(0, 0, 3, 6),
|
ReqXHeight: 4,
|
||||||
reqXHeight: 4,
|
ScaleMode: YScaleModeAnchored,
|
||||||
wantWidth: 2,
|
},
|
||||||
|
cvsAr: image.Rect(0, 0, 3, 6),
|
||||||
|
wantWidth: 2,
|
||||||
want: &YDetails{
|
want: &YDetails{
|
||||||
Width: 2,
|
Width: 2,
|
||||||
Start: image.Point{1, 0},
|
Start: image.Point{1, 0},
|
||||||
@ -123,13 +131,15 @@ func TestY(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "success for adaptive scale",
|
desc: "success for adaptive scale",
|
||||||
minVal: 1,
|
yp: &YProperties{
|
||||||
maxVal: 6,
|
Min: 1,
|
||||||
mode: YScaleModeAdaptive,
|
Max: 6,
|
||||||
cvsAr: image.Rect(0, 0, 3, 4),
|
ReqXHeight: 2,
|
||||||
reqXHeight: 2,
|
ScaleMode: YScaleModeAdaptive,
|
||||||
wantWidth: 2,
|
},
|
||||||
|
cvsAr: image.Rect(0, 0, 3, 4),
|
||||||
|
wantWidth: 2,
|
||||||
want: &YDetails{
|
want: &YDetails{
|
||||||
Width: 2,
|
Width: 2,
|
||||||
Start: image.Point{1, 0},
|
Start: image.Point{1, 0},
|
||||||
@ -142,12 +152,14 @@ func TestY(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "cvsWidth just accommodates the longest label",
|
desc: "cvsWidth just accommodates the longest label",
|
||||||
minVal: 0,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 0,
|
||||||
cvsAr: image.Rect(0, 0, 6, 4),
|
Max: 3,
|
||||||
reqXHeight: 2,
|
ReqXHeight: 2,
|
||||||
wantWidth: 2,
|
},
|
||||||
|
cvsAr: image.Rect(0, 0, 6, 4),
|
||||||
|
wantWidth: 2,
|
||||||
want: &YDetails{
|
want: &YDetails{
|
||||||
Width: 5,
|
Width: 5,
|
||||||
Start: image.Point{4, 0},
|
Start: image.Point{4, 0},
|
||||||
@ -160,12 +172,14 @@ func TestY(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "cvsWidth is more than we need",
|
desc: "cvsWidth is more than we need",
|
||||||
minVal: 0,
|
yp: &YProperties{
|
||||||
maxVal: 3,
|
Min: 0,
|
||||||
cvsAr: image.Rect(0, 0, 7, 4),
|
Max: 3,
|
||||||
reqXHeight: 2,
|
ReqXHeight: 2,
|
||||||
wantWidth: 2,
|
},
|
||||||
|
cvsAr: image.Rect(0, 0, 7, 4),
|
||||||
|
wantWidth: 2,
|
||||||
want: &YDetails{
|
want: &YDetails{
|
||||||
Width: 5,
|
Width: 5,
|
||||||
Start: image.Point{4, 0},
|
Start: image.Point{4, 0},
|
||||||
@ -181,17 +195,12 @@ func TestY(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.desc, func(t *testing.T) {
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
y := NewY(tc.minVal, tc.maxVal)
|
gotWidth := RequiredWidth(tc.yp.Min, tc.yp.Max)
|
||||||
if tc.update != nil {
|
|
||||||
y.Update(tc.update.minVal, tc.update.maxVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
gotWidth := RequiredWidth(tc.minVal, tc.maxVal)
|
|
||||||
if gotWidth != tc.wantWidth {
|
if gotWidth != tc.wantWidth {
|
||||||
t.Errorf("RequiredWidth => got %v, want %v", gotWidth, tc.wantWidth)
|
t.Errorf("RequiredWidth => got %v, want %v", gotWidth, tc.wantWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := y.Details(tc.cvsAr, tc.reqXHeight, tc.mode)
|
got, err := NewYDetails(tc.cvsAr, tc.yp)
|
||||||
if (err != nil) != tc.wantErr {
|
if (err != nil) != tc.wantErr {
|
||||||
t.Errorf("Details => unexpected error: %v, wantErr: %v", err, tc.wantErr)
|
t.Errorf("Details => unexpected error: %v, wantErr: %v", err, tc.wantErr)
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,13 @@ func (lc *LineChart) Draw(cvs *canvas.Canvas) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reqXHeight := axes.RequiredHeight(lc.maxPoints(), lc.xLabels, lc.opts.xLabelOrientation)
|
reqXHeight := axes.RequiredHeight(lc.maxPoints(), lc.xLabels, lc.opts.xLabelOrientation)
|
||||||
yd, err := lc.yAxis.Details(cvs.Area(), reqXHeight, lc.opts.yAxisMode)
|
yp := &axes.YProperties{
|
||||||
|
Min: lc.yMin,
|
||||||
|
Max: lc.yMax,
|
||||||
|
ReqXHeight: reqXHeight,
|
||||||
|
ScaleMode: lc.opts.yAxisMode,
|
||||||
|
}
|
||||||
|
yd, err := axes.NewYDetails(cvs.Area(), yp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("lc.yAxis.Details => %v", err)
|
return fmt.Errorf("lc.yAxis.Details => %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user