How to save and restore NSScrollView scroll position in Swift? - swift

In a macOS project I'm trying to get and set the scroll cursor position of a NSTableView the code seems to work because don't appairs errors but the cursor don't update.
var clipOrigin = tableView.enclosingScrollView?.contentView.bounds.origin // get the position
clipOrigin = CGPoint (x: 0.0, y: 3.0) // set a new position
tableView.enclosingScrollView?.contentView.scroll(to: clipOrigin!) // set the new position
Am I forgetting something?

contentView.bounds.origin will almost certainly give you a point at 0,0 pretty much always as that's not the value you are expecting. bounds tell you an information about a position of the view which displays the canvas, not the inner offset of the scrolled document.
I guess one -documentRect or -documentVisibleRect properties contains the proper offset value you're looking for.

Related

2D Unity: expand UI element based on text to the bottom

I've got a game object (InfoBox) with a..
Vertical Layout Group (Padding 20 on all sides, Control Child Size Height active)
an image
a Content Size Fitter (Vertical Fit set to Preferred Size, Horizontal Unconstrained)
Inside this InfoBox is a Text-Element and every time I update the text, I want the InfoBox to expand or collapse, but to the bottom only. Right now my InfoBox always expands or collapses to both top and bottom, but I don't want that to happen. How can I achieve that? I added some screenshots to better visualise this.
These are my settings for the InfoBox:
And these are my settings for the text:
And this is what happens when I use for example less text, the box collapses from bottom and top, but I want it to stay fixed at the top (on the same line as the green box next to it) and only collapse on the bottom:
Any help is really appreciate!
You main issues looks like you are using a ContentSizeFitter also on the parent object. So it depends how this parent object is aligned with its according parent.
This sentence sounds strange I know but what you did is basically shifting up the alignment responsibility to the parent.
=> Make your UI element aligned to the top and grow downwards.
All you need to do for this is either set
Anchors Min y -> 1
Anchors Max y -> 1
Pivot y -> 1
or simply go to the RectTransform Inspector, open the alignment tool and hold Shift + Alt and click on the top alignment:
For the second instead of using the ContentSizeFitter I prefer to have my own script that only does what it should and nothing more.
You can get the preferredHeight which is exactly the value you are looking for.
The following script simply always applies the preferred height to the text rect. Using [ExecuteAlways] this also works in edit mode. Simply attach it on the same GameObject as the UI.Text component
[ExecuteAlways]
[RequireComponent(typeof(Text))]
[RequireComponent(typeof(RectTransform))]
public class TextHeightFitter : MonoBehaviour
{
[SerializeField] private RectTransform _rectTransform;
[SerializeField] private Text _text;
private void Update()
{
if (!_text) _text = GetComponent<Text>();
if (!_rectTransform) _rectTransform = GetComponent<RectTransform>();
var desiredHeight = _text.preferredHeight;
var size = _rectTransform.sizeDelta;
size.y = desiredHeight;
_rectTransform.sizeDelta = size;
}
}

Drag and drop with pinch zoom doesn't work as expected

In the zoomed mode for pinch-zoom the drag doesn't align properly with the mouse pointer.
I've detailed the problem here:https://stackblitz.com/edit/angular-t7hwqg
I expect the drag to work same way irrespective of the zoom.
I saw in version 8 of angular material they have added #Input('cdkDragConstrainPosition')
constrainPosition: (point: Point, dragRef: DragRef) => Point, which will solve my problem as in the zoomed mode I can write a custom logic to map the drag properly with pointer, but I can't upgrade to version 8 as there are other parts of the application with version 7.
So if someone can suggest what can be done? Either somehow the drag can be modified and take into account the current amount of zoom, or if I can take 'cdkDragConstrainPosition' from version 8 of material and integrate into my current packages.
I had to manually calculate the updated coordinates something like this:
Here imageHeight is the width/height of the DOM element and height is the actual image height that was loaded into the DOM element.
item is the DOM element to be moved around.
this.zoomFactorY = this.imageHeight / this.height;
this.zoomFactorX = this.imageWidth / this.width;
// to be called at every position update
const curTransform = this.item.nativeElement.style.transform.substring(12,
this.item.nativeElement.style.transform.length - 1).split(',');
const leftChange = parseFloat(curTransform[0]);
const topChange = parseFloat(curTransform[1]);
and then update the DOM item's location:
item.location.left = Math.trunc(
item.location.left + leftChange * (1 / this.zoomFactorX)
);
item.location.top = Math.trunc(
item.location.top + topChange * (1 / this.zoomFactorY)
);

FreeText Annotation Appearance Stream In Landscape PDF Using iText

This is my code to create appearance stream for a free text annotation.
cs.rectangle(bbox.getLeft() , bbox.getBottom(), bbox.getWidth(), bbox.getHeight());
cs.fill();
String[] text = new String[1];
text[0] = "BAC"
cs.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), pdfJSAnnotation.getFontSize());
cs.beginText();
cs.setLeading(fontSize + 1.75f);
cs.moveText(0, bbox.getHeight() - fontSize + .75f);
for (String s : text) {
if (s.equals("\n"))
cs.newlineText();
else
cs.showText(s);
}
cs.endText();
where cs is PdfAppearance, bbox is Rectangle. This works okay when pdf is portrait. however, im having problems when it is in landscape, say if page rotation is 270.
The text shown is vertical. and even if i use cs.transform() to rotate, it does not even rotate properly. I also tried to save the state, do a rotate then display text and then call cs.restoreState() after cs.endText() but the outcome is still not correct.
any ideas?
the rectangle is correct since the 1st 2 lines where it fills a rectangle shape is correctly displayed. it is the text i am having problems with.
The solution to this is:
- set appearance dimension to (height,width) since it is 270 degrees.
Then in the PdfAppearance object:
translate it to (height, 0);
rotate to 270
translate to (-height,-height);
(Tried to remove this post but there is no option available)

Positioning Nodes At Below the Bottom of the Screen (Spritekit)

Hello I'm trying to spawn bullets at the bottom of my screen to travel upwards but the current code that I have spawns the bullets at the top of the screen. I've tried making the height negative and nothing happened. Here's the code I'm working with, thanks.
let randomBulletPosition = GKRandomDistribution(lowestValue: -300, highestValue: 300)
let position = CGFloat(randomBulletPosition.nextInt())
bullet.position = CGPoint(x: position, y: self.frame.size.height + bullet.size.height)
Some nice conversions will help you.
Now, do not do this all the time, this should be a one and done type deal, like in a lazy property.
First, we want to get the bottom of our view
let viewBottom = CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY) //In a UIView, 0,0 is the top left corner, so we look to bottom middle
Second, we want to convert the position to the scene
let sceneBottom = scene!.view!.convert(viewBottom, to:scene!)
Finally we want to convert to whatever node you need it to be a part of. (This is optional if you want to place it on the scene)
let nodeBottom = scene!.convert(sceneBottom,to:node)
Code should look like this:
let viewBottom = CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY)
let sceneBottom = scene!.view!.convert(viewBottom!, to:scene!)
let nodeBottom = scene!.convert(sceneBottom,to:node)
Of course, this is a little ugly.
Thankfully we have convertPoint and convert(_from:) to clean things up a little bit
let sceneBottom = scene.convertPoint(from:viewBottom)
Which means we can clean up the code to look like this:
let sceneBottom = scene.convertPoint(from:CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY))
let nodeBottom = node.convert(sceneBottom,from:scene!)
Then we can make it 1 line as:
let nodeBottom = node.convert(scene.convertPoint(from:CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY),from:scene!)
As long as the node is available to the class, we can make it lazy:
lazy var nodeBottom = self.node.convert(self.scene!.convertPoint(CGPoint(x:self.scene!.view!.midX,y:self.scene!.view!.frame.maxY),from:self.scene!)
This means the first time you call nodeBottom, it will do these calculations for you and store it into memory. Everytime after that, the number is preserved.
Now that you know where the bottom of the screen is in the coordinate system you want to use, you can assign the x value to whatever your random is producing, and you can subtract the (node.height * (1 - node.anchorPoint.y)) to fully hide your node from the scene.
Now keep in mind, if your node moves between various parents, this lazy will not update.
Also note, I unwrapped all optionals with !, you may want to be using ? and checking if it exists first.

Flipping a child sprite's xscale in Spritekit using Swift

Alright I'm offically stumped. I've been able to figure out my problems myself in the past but I'm lost on this one.
I'm trying to flip a child sprite's xscale. I want the flip to occur when the child's x position is negative. With the code below, the sprite does flip, every time the sprite reaches negative position, it loops back and forth flipping until reaching positive again.
I've tried numerous variations, but this is the code in it's simplest form. Any help or alternatives would be appreciative.
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
let pin = childNodeWithName(Pin1) as SKSpriteNode!
let guyPoint = guy.convertPoint(guy.position, fromNode: pin)
if guyPoint.x <= 0 {
guy.xScale = -1
}
else {
guy.xScale = 1
}
}
So if it is constantly flipping it's probably an issue of coordinate space. So check to make sure your convertPoint method is accurately returning the point you want. I would use println() to see what's going on there.
Probably what's happening is you want to flip the xScale when the child node is negative in the scene space or something (i.e. when the child is off the screen) but instead guyPoint might be the position of the child in its parent's coordinate space (so relative to the parent).
Also try with and without the else{} part to see if that changes anything.