1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-27 21:56:19 -04:00
OpenDiablo2/d2core/d2ui/tooltip.go
juander 01927d0f3b d2core/d2ui: Add checks to all widgets if they implement Widget
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.
2020-11-09 18:13:17 +01:00

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
}