core icon indicating copy to clipboard operation
core copied to clipboard

Fine grained movements of widgets in a frame with no layout.

Open DCowboy opened this issue 1 year ago • 5 comments

Describe the feature

After failing to make what I was interested in clear enough for an off-handed question, and not finding any examples in cogent/cogent that did anything in the realm of what I was looking to do, It was suggested I make a new issue with full details to see the best way to go about it if a good way exists within what's currently supported or to request the feature be supported if need be.

In my specific use case, I'm interested in making a ticker made of buttons within a frame. While I do understand that Cogent is designed differently than other GUI libraries to be smaller faster and more responsive, I only currently know how to explain it in terms of how those other libraries work. So, please bear with me on that.

Using other libraries, this would usually be controlled by defining a tick() function that:

  1. Changed the positions of all the buttons in a slice or map, (as buttons could be added or removed as needed) to the left by a speed amount.
  2. If the left most button was entirely past the frame's border, and supposedly completely out view as a result, set that button's position to the last button's position + width+speed, (so that it sits right up against the button now preceding it,)
  3. Call the update function to reflect the changes.

If this were put on a loop, (probably best implemented in a goroutine; given the way Cogent looks to be designed,) it would show continuous movement.

There are lots of use cases where changing a widget's position, size, (or shape- mostly in the case of canvas items,) could be desirable in a Graphic User Interface; whether the changes are brought about by a looped function for constant movement, or another widget like a button's function, or even a key bind.

Is there a good way to go about this type of thing in the current infrastructure?

Update: Upon trying to make things work under the current structure, I seem to have run into an issue just setting initial positions Using NoLayout in a frame that's also using Maker.

Perhaps I'm doing something wrong. I tried a few different ways on my end before heading tot the playground to see if setting up an even simpler version starting from the tree example would work. Yet I got the same results. Here is the playground version:

package main


func main() {
	b := core.NewBody()
	btnWidth := float32(50)
	number := 3
	spinner := core.Bind(&number, core.NewSpinner(b)).SetMin(0)
	buttons := core.NewFrame(b)
	buttons.Styler(func(s *styles.Style) {
		s.Display = styles.NoLayout
		s.Overflow.Set(styles.OverflowHidden)
		s.Min.Set(units.Dp(300), units.Dp(50))
		s.Max.Set(units.Dp(300), units.Dp(50))
		s.Border.Style.SetAll(styles.BorderInset)
		s.Border.Width.SetAll(units.Dp(2))
	})
	buttons.Maker(func(p *tree.Plan) {
		for i := range number {
			tree.AddAt(p, strconv.Itoa(i), func(w *core.Button) {
				w.Styler(func(s *styles.Style) {
					s.Min.Set(units.Dp(btnWidth), units.Dp(20))
					s.Max.Set(units.Dp(btnWidth), units.Dp(20))
					//s.Padding.SetAll(units.Dp(0))
					s.Pos.Set(units.Dp(btnWidth*float32(i)), units.Dp(0))
					//s.Pos = units.XY{X: units.Dp(btnWidth*float32(i)), Y: units.Dp(0)}
					core.MessageSnackbar(b, s.Pos.String())
					
				})
				w.SetText("btn " + strconv.Itoa(i))
				
			})
		}
	})
	spinner.OnChange(func(e events.Event) {
		buttons.Update()
	})
	b.RunMainWindow()
}

After I get them initially set up, using the Styler, I'll still have to figure out how to make it conditional so the positions can then be altered when updated. But so far, when in NoLayout, Only button 0 shows when number is greater than 0. I've added a snackbar to the playground to replace the Println I was using in my desktop editor to show at least for the last button, that the position should have been set.

Am I going about this the wrong way?
Or Would now be a good time to suggest a new other type frame widget? Perhaps with a name like XYFrame or a better name as I confess to not being the best at naming things. This frame could then handle all NoLayout scenarios and you could remove that option from regular frames.

XYFrame would automatically be NoLayout. It would need provide easy ways to access it's children's geometry to make it easy for controlling functions and/or the children themselves to reference. It would also be good if it assisted with functions to allow it's children to do things like:

  1. change position/move(new units.XY)
  2. resize (new units.XY)
  3. rotate(transform to change angle between 0 and 359 degrees - which would resize bounding box)
  4. check overlap (handy and seems to complete the set for basic things done with widgets that aren't static)
  5. Perhaps a couple other things I'm just not thinking of this late.

Note the things above are also precursors to the the functions that would also be needed for movement for the X and Y axis movement in XYZ.

Sorry for the long-windedness with this update, but I figured since I was thinking about making the suggestion for an easier way to do things, might as well try to make the suggestion as complete as possible for most common use cases of non-static GUI elements.

Relevant code

No response

DCowboy avatar Aug 28 '24 00:08 DCowboy

Thank you for filing this issue and providing this update, and apologies for the late response. I will look at your code and get back to you soon.

kkoreilly avatar Aug 30 '24 14:08 kkoreilly

No worries about late responses. I realize that you're busy. I can be patient since my project still has a lot of back end work that needs done too.

DCowboy avatar Sep 02 '24 15:09 DCowboy

I discovered that we actually don't have any code implementing s.Pos currently, which is why it isn't working. We did at some point and it shouldn't be too hard to implement again. This isn't our highest priority, but we will do it at some point relatively soon, and I can help you get your code working after that. Feel free to ping us again once you have finished more of your back-end work.

Also, just in case you don't already know, if you are making something like a game, you might be better suited using a canvas or SVG widget, in which it is very easy to do these kind of fine-grained dynamic manipulations.

kkoreilly avatar Sep 02 '24 20:09 kkoreilly

I discovered that we actually don't have any code implementing s.Pos currently, which is why it isn't working. We did at some point and it shouldn't be too hard to implement again. This isn't our highest priority, but we will do it at some point relatively soon, and I can help you get your code working after that. Feel free to ping us again once you have finished more of your back-end work.

Also, just in case you don't already know, if you are making something like a game, you might be better suited using a canvas or SVG widget, in which it is very easy to do these kind of fine-grained dynamic manipulations.

I understood that. I explained above that my use case is making a ticker. Specifically, one that will be used for a crypto trading tool. reducing multiple browser tabs of information to a small window.

DCowboy avatar Sep 02 '24 20:09 DCowboy

Okay, I understand. We will definitely get this working when we have the time.

kkoreilly avatar Sep 02 '24 20:09 kkoreilly

I figured I'd check and see where you guys are at with this.

I got my back end stuff caught up earlier than expected and tried playing with other libraries in the meantime to give you guys time. Working with Gio ui in particular has been educational and at this point has given me new appreciation for what you guys do for users under the hood. While I was able to deal with the component that spawned this issue for this library, I really don't want to roll my own widgets like listboxes (choosers) and such; as realizing what will have to go into them exemplifies what I want in a gui platform in the first place.

DCowboy avatar Nov 11 '24 13:11 DCowboy

Thank you for pinging us on this, and we appreciate your feedback. We have been busy with other issues, but we will prioritize this issue now, and we should have it implemented within a couple of days.

kkoreilly avatar Nov 11 '24 19:11 kkoreilly

Thank you. I'll keep an eye out.

DCowboy avatar Nov 11 '24 21:11 DCowboy

s.Pos is implemented as of #1303, so you should be able to implement your use case using it now. If you have any issues getting it working, I am happy to help.

kkoreilly avatar Nov 13 '24 23:11 kkoreilly

We also renamed NoLayout to Custom in #1305 to better represent the functionality.

kkoreilly avatar Nov 14 '24 16:11 kkoreilly

We also renamed NoLayout to Custom in #1305 to better represent the functionality.

That would probably be what wasn't making sense this morning...lol

DCowboy avatar Nov 14 '24 16:11 DCowboy