fixed graph windows

This commit is contained in:
grimsace
2026-03-24 10:18:31 -05:00
parent 2e91081c61
commit 7b2f7140aa
+43 -38
View File
@@ -42,17 +42,7 @@ func (r *barGraphCanvasRenderer) Layout(size fyne.Size) {
} }
func (r *barGraphCanvasRenderer) MinSize() fyne.Size { func (r *barGraphCanvasRenderer) MinSize() fyne.Size {
minWidth := float32(900) return fyne.NewSize(320, 240)
if r.graph.stats != nil {
outcomes := r.graph.stats.GetSortedOutcomes()
// Calculate minimum width required for bars
// Assume minimum 25 pixels per bar (including spacing) plus padding
requiredWidth := float32(100+20) + float32(len(outcomes))*25
if requiredWidth > minWidth {
minWidth = requiredWidth
}
}
return fyne.NewSize(minWidth, 550)
} }
func (r *barGraphCanvasRenderer) Refresh() { func (r *barGraphCanvasRenderer) Refresh() {
@@ -72,19 +62,27 @@ func (r *barGraphCanvasRenderer) Refresh() {
roundedMaxPercent = 5 roundedMaxPercent = 5
} }
// Padding
topPadding := float32(75)
bottomPadding := float32(80)
leftPadding := float32(100)
rightPadding := float32(20)
size := r.graph.Size() size := r.graph.Size()
if size.Width == 0 || size.Height == 0 { if size.Width == 0 || size.Height == 0 {
size = fyne.NewSize(900, 550) size = fyne.NewSize(900, 550)
} }
// Padding and typography scale with the available area so the graph fits the window.
topPadding := clamp(size.Height*0.14, 48, 75)
bottomPadding := clamp(size.Height*0.15, 56, 80)
leftPadding := clamp(size.Width*0.12, 60, 100)
rightPadding := clamp(size.Width*0.03, 16, 24)
graphWidth := size.Width - leftPadding - rightPadding graphWidth := size.Width - leftPadding - rightPadding
graphHeight := size.Height - topPadding - bottomPadding graphHeight := size.Height - topPadding - bottomPadding
if graphWidth <= 0 || graphHeight <= 0 {
return
}
titleSize := clamp(size.Height*0.03, 12, 16)
bodyTextSize := clamp(size.Height*0.02, 9, 11)
labelTextSize := clamp(size.Height*0.022, 10, 12)
tickTextSize := clamp(size.Height*0.018, 8, 10)
// Background // Background
background := canvas.NewRectangle(color.NRGBA{R: 20, G: 20, B: 20, A: 255}) background := canvas.NewRectangle(color.NRGBA{R: 20, G: 20, B: 20, A: 255})
@@ -108,32 +106,32 @@ func (r *barGraphCanvasRenderer) Refresh() {
// Title // Title
title := canvas.NewText("Probability Distribution", color.White) title := canvas.NewText("Probability Distribution", color.White)
title.TextSize = 16 title.TextSize = titleSize
title.Move(fyne.NewPos(leftPadding, 5)) title.Move(fyne.NewPos(leftPadding, 5))
r.objects = append(r.objects, title) r.objects = append(r.objects, title)
// Statistics info line 1 // Statistics info line 1
statsLine1 := canvas.NewText(fmt.Sprintf("Range: %d to %d | Total Outcomes: %d", stats.MinValue, stats.MaxValue, stats.Total), color.White) statsLine1 := canvas.NewText(fmt.Sprintf("Range: %d to %d | Total Outcomes: %d", stats.MinValue, stats.MaxValue, stats.Total), color.White)
statsLine1.TextSize = 11 statsLine1.TextSize = bodyTextSize
statsLine1.Move(fyne.NewPos(leftPadding, 22)) statsLine1.Move(fyne.NewPos(leftPadding, 5+title.MinSize().Height))
r.objects = append(r.objects, statsLine1) r.objects = append(r.objects, statsLine1)
// Statistics info line 2 // Statistics info line 2
statsLine2 := canvas.NewText(fmt.Sprintf("Average: %.2f | Most Common: %d", stats.Average, stats.MostCommon), color.White) statsLine2 := canvas.NewText(fmt.Sprintf("Average: %.2f | Most Common: %d", stats.Average, stats.MostCommon), color.White)
statsLine2.TextSize = 11 statsLine2.TextSize = bodyTextSize
statsLine2.Move(fyne.NewPos(leftPadding, 36)) statsLine2.Move(fyne.NewPos(leftPadding, 5+title.MinSize().Height+statsLine1.MinSize().Height))
r.objects = append(r.objects, statsLine2) r.objects = append(r.objects, statsLine2)
// Y-axis label // Y-axis label
yLabel := canvas.NewText("Probability (%)", color.White) yLabel := canvas.NewText("Probability (%)", color.White)
yLabel.TextSize = 12 yLabel.TextSize = labelTextSize
yLabel.Move(fyne.NewPos(15, topPadding+graphHeight/2-40)) yLabel.Move(fyne.NewPos(clamp(leftPadding*0.15, 8, 15), topPadding+graphHeight/2-yLabel.MinSize().Height/2))
r.objects = append(r.objects, yLabel) r.objects = append(r.objects, yLabel)
// X-axis label // X-axis label
xLabel := canvas.NewText("Result Value", color.White) xLabel := canvas.NewText("Result Value", color.White)
xLabel.TextSize = 12 xLabel.TextSize = labelTextSize
xLabel.Move(fyne.NewPos(leftPadding+graphWidth/2-30, topPadding+graphHeight+50)) xLabel.Move(fyne.NewPos(leftPadding+graphWidth/2-xLabel.MinSize().Width/2, topPadding+graphHeight+clamp(bottomPadding*0.35, 18, 28)))
r.objects = append(r.objects, xLabel) r.objects = append(r.objects, xLabel)
// Y-axis tick marks and labels // Y-axis tick marks and labels
@@ -152,19 +150,19 @@ func (r *barGraphCanvasRenderer) Refresh() {
// Label // Label
label := canvas.NewText(fmt.Sprintf("%.0f%%", percent), color.White) label := canvas.NewText(fmt.Sprintf("%.0f%%", percent), color.White)
label.TextSize = 10 label.TextSize = tickTextSize
label.Move(fyne.NewPos(leftPadding-50, yPos-7)) label.Move(fyne.NewPos(leftPadding-50, yPos-7))
r.objects = append(r.objects, label) r.objects = append(r.objects, label)
} }
// Draw bars // Draw bars
numBars := len(outcomes) numBars := len(outcomes)
barWidth := (graphWidth - float32(numBars+1)*2) / float32(numBars)
if barWidth < 2 {
barWidth = 2
}
barSpacing := float32(2) barSpacing := float32(2)
totalSpacing := float32(numBars+1) * barSpacing
barWidth := (graphWidth - totalSpacing) / float32(numBars)
if barWidth < 1 {
barWidth = 1
}
// Calculate label step to prevent overlapping // Calculate label step to prevent overlapping
labelStep := calculateLabelStep(graphWidth, numBars) labelStep := calculateLabelStep(graphWidth, numBars)
@@ -176,7 +174,7 @@ func (r *barGraphCanvasRenderer) Refresh() {
barHeight := (float32(percentage) / float32(roundedMaxPercent)) * graphHeight barHeight := (float32(percentage) / float32(roundedMaxPercent)) * graphHeight
// X position // X position
xPos := leftPadding + float32(i)*(barWidth+barSpacing*2) + barSpacing xPos := leftPadding + barSpacing + float32(i)*(barWidth+barSpacing)
// Draw bar // Draw bar
bar := canvas.NewRectangle(color.NRGBA{R: 100, G: 180, B: 255, A: 255}) bar := canvas.NewRectangle(color.NRGBA{R: 100, G: 180, B: 255, A: 255})
@@ -196,7 +194,7 @@ func (r *barGraphCanvasRenderer) Refresh() {
if isFirst || isLast || showIntermediate { if isFirst || isLast || showIntermediate {
label := canvas.NewText(fmt.Sprintf("%d", value), color.White) label := canvas.NewText(fmt.Sprintf("%d", value), color.White)
label.TextSize = 10 label.TextSize = tickTextSize
// Center label under bar // Center label under bar
label.Alignment = fyne.TextAlignCenter label.Alignment = fyne.TextAlignCenter
@@ -207,6 +205,16 @@ func (r *barGraphCanvasRenderer) Refresh() {
} }
} }
func clamp(value, minValue, maxValue float32) float32 {
if value < minValue {
return minValue
}
if value > maxValue {
return maxValue
}
return value
}
func calculateLabelStep(graphWidth float32, numBars int) int { func calculateLabelStep(graphWidth float32, numBars int) int {
labelWidthEstimate := float32(35) // Estimate width of a label labelWidthEstimate := float32(35) // Estimate width of a label
maxLabels := int(graphWidth / labelWidthEstimate) maxLabels := int(graphWidth / labelWidthEstimate)
@@ -238,12 +246,9 @@ func ShowStatisticsWindow(expression string) {
// Create the bar graph // Create the bar graph
graph := newBarGraphCanvas(stats) graph := newBarGraphCanvas(stats)
// Create scroll container
scroll := container.NewScroll(graph)
// Create and show the window // Create and show the window
window := fyne.CurrentApp().NewWindow("Statistics: " + expression) window := fyne.CurrentApp().NewWindow("Statistics: " + expression)
window.SetContent(scroll) window.SetContent(container.NewMax(graph))
window.Resize(fyne.NewSize(900, 550)) window.Resize(fyne.NewSize(900, 550))
window.Show() window.Show()
} }