gtkmm Gtk::Layout negative child position not setting its absolute position - infinite-scroll

The description of Gtk::Layout says
Infinite scrollable area containing child widgets and/or custom drawing
I put a Gtk::Layout inside a Gtk::ScrolledWindow, gave the Gtk::Layout a size of 400x400 and then placed a Gtk::Button at (450, 450), but the scrollbars only appeared until the scrolled window was resized to 400x400, not (450+button-width x 450+button-height). So I had to move the bottom-right corner of the layout by connecting a handler to button's signal_size_allocate() signal and manually call Gtk::Layout::set_size() function to resize it up to button's boundary. Now the scrolled window shows scrollbars to reach the button. Up to this everything was OK.
class LayoutWindowTest : public ApplicationWindow {
ScrolledWindow sw;
Layout l;
Button b;
public:
LayoutWindowTest()
: l(), b("test") {
set_title("layout test");
set_size_request(400, 400);
sw.set_hadjustment(l.get_hadjustment());
sw.set_vadjustment(l.get_vadjustment());
l.set_size(400, 400);
sw.add(l);
add(sw);
// b.get_allocation() won't work because button has not been allocated a
// size yet
b.signal_size_allocate().connect(
[this](Allocation& btn_sz) {
l.set_size(btn_sz.get_x() + btn_sz.get_width(),
btn_sz.get_y() + btn_sz.get_height());
});
l.put(b, 450, 450);
show_all_children();
}
virtual ~LayoutWindowTest() {}
};
Initial window showing scrollbars and then scrolled to bottom-right corner to show button
Now I need to do the same thing for the top-left corner, i.e. put the button out of visible boundary of scrolled window and then use the scrollbars to reach the button. I tried putting the button at (-10, -10), but unlike the previous case I can't set layout's top-left corner with code by resizing it, so can't move the layout's scrollbars. When I resize the scrolled window manually by its top-left corner the button moves towards top-left with it instead of staying there. How to remedy this situation?
Initial window with button at (-10, -10) and no scrollbars, tried resizing the window by top-left handle but button moves with it
In short, how can I scroll in both top-left and bottom-right directions infinitely?

Related

Unity - How to scroll a scrollbar for a ScrollRect smoothly?

I have a ScrollRect to which I add content to. When it reaches the point where the content is longer than the ScrollRect (ie when the ScrollBar's value changes from 0), I want the ScrollRect to scroll all the way down (I do this by tweening the ScrollBar's value until it reaches 0). However, my problem is that I can't figure out how to do this smoothly over time.
Here's my code snippet:
public void Update() {
if (scrollbar.size < 1 || scrollbar.value > 0) {
LeanTween.value(scrollbar.value, 0, duration).setOnUpdate((float val) => {
if (scrollbar.value == 0) {
LeanTween.cancel(this.gameObject);
} else {
scrollbar.value = val / scrollAdjustment;
}
});
}
}
I tried using "Time.deltaTime" and "Time.time" in place of duration and it did not seem to matter. Here's a gif of what happens:
(In this example, I used "duration" that had the value of 5 (the idea was to have the transition take 5 seconds) and "scrollAdjustment" was 50 but it did not seem to matter what I set either of these values to.
You can see it instantly snaps to the bottom. I'd like this to be a smooth transition. Any help is appreciated!
My settings:
Then here is me scrolling with my mouse wheel while the autoscroll feature is turned off (because I'm using Rewired, I am intercepting an input called "ZoomIn" and "ZoomOut" and add "0.01f * scrollSpeed" (where scrollSpeed is 15 in this case):
You shouldn't need to add any additional code to make the scroll bar function as the way you want it to. Try deactivating your script and mess with your scroll bar. Make sure you have your Number Of Steps On Your Scrollbar Component as 0 to make it smooth. If it's still not working, send some screenshots of your scroll gameobject to see if the rect is the problem or something else.

Dragged Image Location

I am dragging an image to an NSView.
Works fine, except that if I insert the dragged image at the received NSDraggingInfo.draggingLocation, the image is suddenly offsetted from its current drag dimmed drawing.
Indeed, the user has taken the image with the cursor by clicking "somewhere" in the image, there is therefore an offset between the bottom left corner of the image, and the cursor itself. Then, the user drags, and drops the image. If I position the dropped image at the cursor position, the image suddenly shifts...
I tried to use NSDraggingInfo.draggedImageLocation, but the result is even worse. NSDraggingInfo.draggedImageLocation seems to contain an position information that is not at all what Apple describes in the doc.
How can I get the bottom left (or other) point of the dragged image so that I can have a smooth drop and insertion ?
Note: this is a cross-app drag & drop, so I don't have any information at the time the user starts the drag.
Edit: added some information as per comments
The image shifts only when dropped
Here is the code of the performDragOperation func
public func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
let pboard = sender.draggingPasteboard
if let images = pboard.readObjects(forClasses: [NSImage.self],
options: nil) as? [NSImage] {
for image in images {
self.imageDropDelegate?.receive(image: image,
at: sender.draggingLocation)
print("drop point : \(sender.draggingLocation)")
print("image point : \(sender.draggedImageLocation)")
}
}
return true
}
The delegate just creates an image view at the point it is given. The problem is that sender.draggedImageLocation is the poirnt where the cursor is when the mouse up event is detected, which is different from the bottom left corner of the dragged image.
Apple doc says sender.draggedImageLocation should be what I am after, but the prints says:
drop point : (413.18212890625, 458.5313720703125)
image point : (-1438.0, 969.0)
drop point : (439.2493896484375, 443.3453369140625)
image point : (-1438.0, 969.0)
The drop point is indeed the position of the cursor when I release the mouse (drop).
But image point is just completely un-understandable to me.
And I checked that sender.draggingFormation is 1 (so 'none')

Unity: add different scroll speeds in UI Scroll Rect

In Unity, I created a UI Scroll Rect Object. This object has two children, a Button Handler with different Buttons, and a Background.
Using it, both the Buttons and the Background are scrolling at the same speed. I want the Buttons to scroll faster than the Background, thus creating an effect of depth to the scrolling.
I can not find any options in the Objects or the Scroll Rect for this. Any ideas?
This will require a tiny bit of scripting. The best way in my opinion would involve following steps:
a) for each button, add a component that remembers its start position.
b) grab a scrollrect instance in parent
c) using it to grab an instance of ScrollBar
d) scrollbars have onValueChanged(float) callbacks, you can bind to, to know when the scroll position changes (to avoid doing checks in Update)
e) every time a scrollbar has moved (This will work regardless of whether the user used the scrollbar, or used another mean of scrolling, as the scrollrect will move the scrollbar, which will fire the event anyways), you get a callback with current scrollbar position which will be equal to normalized scrollrect position (0.1)
f) use that value to offset your localposition (something value*parallaxVector2), this should give you a nice cheap depth effect
Here's an example implementation
public class ScrolleRectDepthButton : MonoBehaviour
{
RectTransform content; // we'll grab it for size reference
RectTransform myRect;
public float parallaxAmount = 0.05f;
public Vector2 startPosition;
void Start()
{
myRect = GetComponent<RectTransform>();
startPosition = myRect.anchoredPosition;
ScrollRect scrollRect = GetComponentInParent<ScrollRect>();
content = scrollRect.content;
Scrollbar scrollbar = scrollRect.verticalScrollbar;
scrollbar.onValueChanged.AddListener(OnScrollbarMoved);
}
void OnScrollbarMoved(float f)
{
myRect.anchoredPosition = startPosition - (1 - f) * parallaxAmount * content.rect.height * Vector2.up;
}
}

How to clone a node to appear exactly on top in a different pane

In my (full-screen) program I have several items displayed in a layout. What I would like to do is that when I tap or click on a item is to show a full screen editor. The idea is to have transition from the item shown to the editor.
When the editor is shown I first display a semi-transparent view on top of the stackpane, underneath the other items are still visible. The selected item should 'move' to the upper layer, and then start to transform to its editor shape. Closing the editor should of course be a reverse course of actions.
The first attempt was to move the from its container to the upper layer, but JavaFX complained about the bound properties. I rather not have to code a whole bunch of bind/unbinds, so I assumed this was not the route.
My next attempt was something like this:
private volatile FullScreenService fullscreenService;
private void showFullPhoto(MouseEvent e) {
FullScreenService service = fullscreenService;
if (service != null) {
try {
Node node = (Node) e.getSource();
ImageView photoView = (ImageView)node.lookup("#image");
Image image = photoView.getImage();
Pane pane = new Pane();
pane.setPrefSize(1920d, 1080d);
ImageView copy = new ImageView(image);
copy.setRotate(node.getRotate());
node.setVisible(false);
Bounds bounds = photoView.localToScene(photoView.getBoundsInLocal());
copy.setLayoutX(bounds.getMinX());
copy.setLayoutY(bounds.getMinY());
pane.getChildren().add(copy);
service.requestFullScreen(pane);
} catch (InUseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
The idea is to hide the original view and 'clone' the part that should be shown (and then transitioned). In this case I extract the image part out of a photo (that also has a border and caption), and make a copy on the editor screen.
However the location of the image does not match the original location exactly, it is off by a couple of pixels, making the image 'jump'.
I've created the pane to be exact the size of the screen, so I thought I could assume scene coordinates are the same as the new node's coordinates.
Abstracting my question: given two overlapping panes, how to make sure a node is exactly on top of another node?

Position a UI button on bottom left of the viewport/screen?

How do I place a UI Button (the new UI) so that it is always at the bottom-left on the screen/viewport? My idea was to do it in code like this:
void Awake () {
fireButton.transform.position = new Vector3(Screen.width - 50, Screen.height - 50, 0);
}
It is not working at all. How can I best do this?
Instead of doing it in code, click on the UIButton in the scene or hierarchy then go into the inspector and in the top left of the transform component you will see a square, click it, hold shift and alt and then click the 'Bottom Left' square to latch it to that side of the screen.