mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-10-01 23:56:16 -04:00
01927d0f3b
this also adds missing methods to elements not implementing widget. Note here that we do not enable sprite and label, as this would produce a crazy amount of linter warnings due to render() requiering error handling then, which non of the callers handle. Since we remove the render calls later anyways, we can postpone this static check for now.
203 lines
4.4 KiB
Go
203 lines
4.4 KiB
Go
package d2ui
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
|
)
|
|
|
|
const (
|
|
blackAlpha70 = 0x000000C8
|
|
screenWidth = 800
|
|
screenHeight = 600
|
|
)
|
|
|
|
// static check that Tooltip implements widget
|
|
var _ Widget = &Tooltip{}
|
|
|
|
// Tooltip contains a label containing text with a transparent, black background
|
|
type Tooltip struct {
|
|
*BaseWidget
|
|
lines []string
|
|
label *Label
|
|
backgroundColor int
|
|
originX tooltipXOrigin
|
|
originY tooltipYOrigin
|
|
boxEnabled bool
|
|
}
|
|
|
|
type tooltipXOrigin = int
|
|
type tooltipYOrigin = int
|
|
|
|
const (
|
|
// TooltipYTop sets the Y origin of the tooltip to the top
|
|
TooltipYTop tooltipYOrigin = iota
|
|
// TooltipYCenter sets the Y origin of the tooltip to the center
|
|
TooltipYCenter
|
|
// TooltipYBottom sets the Y origin of the tooltip to the bottom
|
|
TooltipYBottom
|
|
)
|
|
|
|
const (
|
|
// TooltipXLeft sets the X origin of the tooltip to the left
|
|
TooltipXLeft tooltipXOrigin = iota
|
|
// TooltipXCenter sets the X origin of the tooltip to the center
|
|
TooltipXCenter
|
|
// TooltipXRight sets the X origin of the tooltip to the right
|
|
TooltipXRight
|
|
)
|
|
|
|
// NewTooltip creates a tooltip instance. Note here, that we need to define the
|
|
// orign point of the tooltip rect using tooltipXOrigin and tooltinYOrigin
|
|
func (ui *UIManager) NewTooltip(font,
|
|
palette string,
|
|
originX tooltipXOrigin,
|
|
originY tooltipYOrigin) *Tooltip {
|
|
label := ui.NewLabel(font, palette)
|
|
label.Alignment = d2gui.HorizontalAlignCenter
|
|
|
|
base := NewBaseWidget(ui)
|
|
|
|
res := &Tooltip{
|
|
BaseWidget: base,
|
|
backgroundColor: blackAlpha70,
|
|
label: label,
|
|
originX: originX,
|
|
originY: originY,
|
|
boxEnabled: true,
|
|
}
|
|
res.manager = ui
|
|
|
|
return res
|
|
}
|
|
|
|
// SetTextLines sets the tooltip text in the form of an array of strings
|
|
func (t *Tooltip) SetTextLines(lines []string) {
|
|
t.lines = lines
|
|
}
|
|
|
|
// SetText sets the tooltip text and splits \n into lines
|
|
func (t *Tooltip) SetText(text string) {
|
|
t.lines = strings.Split(text, "\n")
|
|
}
|
|
|
|
// SetBoxEnabled determines whether a black box is drawn around the text
|
|
func (t *Tooltip) SetBoxEnabled(enable bool) {
|
|
t.boxEnabled = enable
|
|
}
|
|
|
|
func (t *Tooltip) adjustCoordinatesToScreen(maxW, maxH, halfW, halfH int) (rx, ry int) {
|
|
var xOffset, yOffset int
|
|
|
|
switch t.originX {
|
|
case TooltipXLeft:
|
|
xOffset = maxW
|
|
case TooltipXCenter:
|
|
xOffset = halfW
|
|
case TooltipXRight:
|
|
xOffset = 0
|
|
}
|
|
|
|
renderX := t.x
|
|
if (t.x + xOffset) > screenWidth {
|
|
renderX = screenWidth - xOffset
|
|
}
|
|
|
|
switch t.originY {
|
|
case TooltipYTop:
|
|
yOffset = 0
|
|
case TooltipYCenter:
|
|
yOffset = halfH
|
|
case TooltipYBottom:
|
|
yOffset = maxH
|
|
}
|
|
|
|
renderY := t.y
|
|
if (t.y + yOffset) > screenHeight {
|
|
renderY = screenHeight - yOffset
|
|
}
|
|
|
|
return renderX, renderY
|
|
}
|
|
|
|
// GetSize returns the size of the tooltip
|
|
func (t *Tooltip) GetSize() (sx, sy int) {
|
|
maxW, maxH := 0, 0
|
|
|
|
for i := range t.lines {
|
|
w, h := t.label.GetTextMetrics(t.lines[i])
|
|
|
|
if maxW < w {
|
|
maxW = w
|
|
}
|
|
|
|
maxH += h
|
|
}
|
|
|
|
return maxW, maxH
|
|
}
|
|
|
|
// Render draws the tooltip
|
|
func (t *Tooltip) Render(target d2interface.Surface) error {
|
|
maxW, maxH := t.GetSize()
|
|
|
|
// nolint:gomnd // no magic numbers, their meaning is obvious
|
|
halfW, halfH := maxW/2, maxH/2
|
|
|
|
renderX, renderY := t.adjustCoordinatesToScreen(maxW, maxH, halfW, halfH)
|
|
|
|
target.PushTranslation(renderX, renderY)
|
|
defer target.Pop()
|
|
|
|
// adjust starting point of the background rect based on the origin point
|
|
// as we always draw a rect from top left
|
|
switch t.originX {
|
|
case TooltipXLeft:
|
|
target.PushTranslation(0, 0)
|
|
case TooltipXCenter:
|
|
target.PushTranslation(-halfW, 0)
|
|
case TooltipXRight:
|
|
target.PushTranslation(-maxW, 0)
|
|
}
|
|
|
|
defer target.Pop()
|
|
|
|
switch t.originY {
|
|
case TooltipYTop:
|
|
target.PushTranslation(0, 0)
|
|
case TooltipYCenter:
|
|
target.PushTranslation(0, -halfH)
|
|
case TooltipXRight:
|
|
target.PushTranslation(0, -maxH)
|
|
}
|
|
|
|
defer target.Pop()
|
|
|
|
// tooltip background
|
|
if t.boxEnabled {
|
|
target.DrawRect(maxW, maxH, d2util.Color(blackAlpha70))
|
|
}
|
|
|
|
// text
|
|
target.PushTranslation(halfW, 0) // text is centered, our box is not
|
|
defer target.Pop()
|
|
|
|
for i := range t.lines {
|
|
t.label.SetText(t.lines[i])
|
|
_, h := t.label.GetTextMetrics(t.lines[i])
|
|
t.label.Render(target)
|
|
target.PushTranslation(0, h)
|
|
}
|
|
|
|
target.PopN(len(t.lines))
|
|
|
|
return nil
|
|
}
|
|
|
|
// Advance is a no-op
|
|
func (t *Tooltip) Advance(elapsed float64) error {
|
|
return nil
|
|
}
|