Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added hoverBackground to buttonRenderer, fixes #1785 #2003

Closed
wants to merge 2 commits into from

Conversation

fpabl0
Copy link
Member

@fpabl0 fpabl0 commented Feb 22, 2021

Description:

Fixes #1785

Checklist:

  • Tests included.
  • Lint and formatter run with no errors.
  • Tests all pass.

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to re-use the existing rectangle which the new one appears immediately above, that way we don’t need more elements rendered for every button.

@fpabl0
Copy link
Member Author

fpabl0 commented Feb 22, 2021

Agreed, however I don't think there is a way for doing it using the current theme.HoverColor(), is that ok?

@andydotxyz
Copy link
Member

Perhaps you can expand on why you don’t think it is possible? What is the problem that gets in the way?

@fpabl0
Copy link
Member Author

fpabl0 commented Feb 22, 2021

@andydotxyz Yes, I tried two alternatives before writing this PR, these alternatives are based on changing only the buttonColor function:

  1. Allow high importance button to behave in the same way as a normal button:
func (r *buttonRenderer) buttonColor() color.Color {
	switch {
	case r.button.Disabled():
		return theme.DisabledButtonColor()
	case r.button.hovered:
		return theme.HoverColor()
	default:
		if r.button.Importance == HighImportance {
			return theme.PrimaryColor()
		}
		return theme.ButtonColor()
	}
}

Captura de Pantalla 2021-02-22 a la(s) 08 43 30

Captura de Pantalla 2021-02-22 a la(s) 08 54 58

  1. Use the hover alpha factor to build the hover color for high importance button:
func (r *buttonRenderer) buttonColor() color.Color {
	switch {
	case r.button.Disabled():
		return theme.DisabledButtonColor()
	case r.button.hovered:
		if r.button.Importance == HighImportance {
			_, _, _, aa := theme.HoverColor().RGBA()
			rr, gg, bb, _ := theme.PrimaryColor().RGBA()
			return color.RGBA{R: uint8(rr), G: uint8(gg), B: uint8(bb), A: uint8(aa)}
		}
		return theme.HoverColor()
	default:
		if r.button.Importance == HighImportance {
			return theme.PrimaryColor()
		}
		return theme.ButtonColor()
	}
}

Captura de Pantalla 2021-02-22 a la(s) 08 52 34

Captura de Pantalla 2021-02-22 a la(s) 08 53 48

Indeed, I think high-importance button without hover color was intentional instead of real bug.

@andydotxyz
Copy link
Member

In version 2 did you consider blending the colours instead of using channels from them in some hybrid approach?
Basically figure out what colour would have been shown if one overlies the other, then set that colour to one rectangle...

Indeed, I think high-importance button without hover color was intentional instead of real bug.

This was not itentional

@fpabl0
Copy link
Member Author

fpabl0 commented Feb 22, 2021

In version 2 did you consider blending the colours instead of using channels from them in some hybrid approach?

Oh yes, that alternative looks good, unfortunately maybe I don't understand very well how to blend colors. I have read this:
https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending, so I tried it but with no success:

func (r *buttonRenderer) getHoverColor() color.Color {
	mainColor := theme.ButtonColor()
	if r.button.Importance == HighImportance {
		mainColor = theme.PrimaryColor()
	}
	srcR, srcG, srcB, srcA := theme.HoverColor().RGBA()
	dstR, dstG, dstB, dstA := mainColor.RGBA()
	outA := srcA + dstA*(0xFFFF-srcA)
	outR := srcR + dstR*(0xFFFF-srcA)
	outG := srcG + dstG*(0xFFFF-srcA)
	outB := srcB + dstB*(0xFFFF-srcA)
	return color.RGBA{R: uint8(outR), G: uint8(outG), B: uint8(outB), A: uint8(outA)}
}

func (r *buttonRenderer) buttonColor() color.Color {
	switch {
	case r.button.Disabled():
		return theme.DisabledButtonColor()
	case r.button.hovered:
		return r.getHoverColor()
	default:
		if r.button.Importance == HighImportance {
			return theme.PrimaryColor()
		}
		return theme.ButtonColor()
	}
}

For normal buttons, works great this implementation:

Captura de Pantalla 2021-02-22 a la(s) 15 16 09

But for high-importance buttons is not:

Captura de Pantalla 2021-02-22 a la(s) 15 16 15

This was not itentional

Oh sorry, I just though it, because it seems that the code enforces that behavior here:

fyne/widget/button.go

Lines 315 to 318 in c29a062

case r.button.Importance == HighImportance:
return theme.PrimaryColor()
case r.button.hovered:
return theme.HoverColor()

@andydotxyz
Copy link
Member

so I tried it but with no success:

My first guess is that it's a uint8 vs uint16 casting issue, that has caught me before.
Try moving the channels to uint8 before doing the calculations, then remove the cast in the return instead.
Also you might want to try using destination alpha instead of source.

@fpabl0
Copy link
Member Author

fpabl0 commented Feb 23, 2021

I have tried your suggestion:

func (r *buttonRenderer) getHoverColor() color.Color {
	toUint8 := func(rr, gg, bb, aa uint32) (uint8, uint8, uint8, uint8) {
		return uint8(rr), uint8(gg), uint8(bb), uint8(aa)
	}
	mainColor := theme.ButtonColor()
	if r.button.Importance == HighImportance {
		mainColor = theme.PrimaryColor()
	}
	srcR, srcG, srcB, srcA := toUint8(theme.HoverColor().RGBA())
	dstR, dstG, dstB, dstA := toUint8(mainColor.RGBA())
	outA := srcA + dstA*(0xFF-srcA)
	outR := (srcR*srcA + dstR*dstA*(0xFF-srcA)) / outA
	outG := (srcG*srcA + dstG*dstA*(0xFF-srcA)) / outA
	outB := (srcB*srcA + dstB*dstA*(0xFF-srcA)) / outA
	return color.NRGBA{R: outR, G: outG, B: outB, A: outA}
}

No success. I am sure that:

what colour would have been shown if one overlies the other, then set that colour to one rectangle

is possible, but I don't manage to know how. So, I will close this to keep things organized, maybe someone with more experience working with colors could help us in this issue :)

@fpabl0 fpabl0 closed this Feb 23, 2021
@fpabl0 fpabl0 deleted the fix/1785 branch February 26, 2021 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants