1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-07-02 19:45:29 +00:00
OpenDiablo2/d2core/d2ui/tooltip.go
juander-ux 1f49df62d1
Ui hud polishing (#938)
* d2ui/tooltip: Make it invisible by default

* d2ui/button: Add GetToggled() method

* d2player/HUD: Add tooltip for minipanel button

* d2ui/button: Add disabled frame to minipanel buttons

* d2ui/widget_group: Add SetEnable method for clickable widgets

* d2player/mini_panel: move menu button here from HUD

* d2ui/button: toggled buttons take preference over disabled buttons

* d2player/help_overlay: Make panel only use widgets

* d2player/hud: Group most widgets into widget group

* d2ui/custom_widget: Allow tooltip to be attached

* d2player/hud: Attach staminaBar tooltip to staminaBar

* d2player/hud: Attach experienceBar tooltip to experienceBar widget

* d2ui/ui_manager: Always draw tooltips last

* d2player/help_overlay: It should be drawn over the HUD

* d2player/globeWidget: Move tooltip here from HUD

* d2core/tooltip: Automatically add tooltips to the uiManager

* d2core/ui_manager: Remove special handling of widgetGroups for rendering

* d2player/help_overlay: Add button to widget group

* d2player/hud: Attack runwalk tooltip to button

* d2player/mini_panel: Add panelButton to its own widget group

* d2core/widget_group: When a clickable is added, it's also added to uiManager

* d2player/globeWidget: make tooltip un/lock on click

* d2player/hud: Add runbutton to widget group

* d2player/mini_panel: Add group for tooltips

this allows us to move the tooltip with the panelbuttons. They can't be
in the general panelGroup as they would all become visible when the
panel is opened.

* d2core/button: Remove debug log when a button with tooltip is hovered
2020-11-21 02:35:32 -08:00

202 lines
4.3 KiB
Go

package d2ui
import (
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
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 = HorizontalAlignCenter
base := NewBaseWidget(ui)
base.SetVisible(false)
res := &Tooltip{
BaseWidget: base,
backgroundColor: blackAlpha70,
label: label,
originX: originX,
originY: originY,
boxEnabled: true,
}
res.manager = ui
ui.addTooltip(res)
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) {
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))
}
// Advance is a no-op
func (t *Tooltip) Advance(elapsed float64) error {
return nil
}