Views Are Merged Instead of Showing Them Separately

Is it possible to merge / intersect two UIViews rather than have them overlap?

One way is to use multiple sibling layers and zPosition. To achieve the effect you add two layers, one for border, one for content. And the border layer has a smaller zPosition than the content. And, of course, move the layers with the UIPanGestureRecognizer.

Showcase

MP4 version

Swift:

import UIKit

class MergingView: UIView {

let borderLayer = CALayer()
let backgroundLayer = CALayer()

override func layoutSubviews() {
super.layoutSubviews()

addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))))

borderLayer.borderWidth = 5
borderLayer.frame = frame
borderLayer.zPosition = 10
borderLayer.borderColor = UIColor.black.cgColor
superview?.layer.addSublayer(borderLayer)

backgroundLayer.frame = CGRect(x: frame.origin.x + 5, y: frame.origin.y + 5, width: frame.width - 10, height: frame.height - 10)
backgroundLayer.zPosition = 20
backgroundLayer.backgroundColor = UIColor.white.cgColor
superview?.layer.addSublayer(backgroundLayer);
}

@objc func handlePan(_ recognizer: UIPanGestureRecognizer) {
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)

let translation = recognizer.translation(in: self)
frame = self.frame.offsetBy(dx: translation.x, dy: translation.y)
recognizer.setTranslation(CGPoint.zero, in: self)

borderLayer.frame = borderLayer.frame.offsetBy(dx: translation.x, dy: translation.y)
backgroundLayer.frame = backgroundLayer.frame.offsetBy(dx: translation.x, dy: translation.y)

CATransaction.commit()
}
}

Objective-C header:

#import <UIKit/UIKit.h>

@interface MVMergingView : UIView

@end

Objective-C implementation:

#import "MVMergingView.h"

@interface MVMergingView ()

@property (strong) CALayer *borderLayer;
@property (strong) CALayer *backgroundLayer;

@end

@implementation MVMergingView

- (void)layoutSubviews {
[super layoutSubviews];

[self addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]];

CALayer *borderLayer = [CALayer layer];
borderLayer.borderWidth = 5.f;
borderLayer.frame = self.frame;
borderLayer.zPosition = 10;
borderLayer.borderColor = UIColor.blackColor.CGColor;
self.borderLayer = borderLayer;
[self.superview.layer addSublayer:borderLayer];

CALayer *backgroundLayer = [CALayer layer];
backgroundLayer.frame = CGRectMake(self.frame.origin.x + 5.f, self.frame.origin.y + 5.f, self.frame.size.width - 10, self.frame.size.height - 10);
backgroundLayer.zPosition = 20;
backgroundLayer.backgroundColor = UIColor.whiteColor.CGColor;
self.backgroundLayer = backgroundLayer;
[self.superview.layer addSublayer:backgroundLayer];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

CGPoint translation = [recognizer translationInView:self];
self.frame = CGRectOffset(self.frame, translation.x, translation.y);
[recognizer setTranslation:CGPointZero inView:self];

self.borderLayer.frame = CGRectOffset(self.borderLayer.frame, translation.x, translation.y);
self.backgroundLayer.frame = CGRectOffset(self.backgroundLayer.frame, translation.x, translation.y);

[CATransaction commit];
}

@end

Example repo: https://github.com/dimitarnestorov/MergingView

Merge two unrelated views into a single view

You want to combine the results, yet be able to tell the rows apart.

To duplicate all columns would be a bit of an overkill. Add a column with info about the source:

SELECT 'v1'::text AS source, clothingid, shoes, shirts
FROM view1

UNION ALL
SELECT 'v2'::text AS source, clothingid, shoes, shirts
FROM view2;

Swift 3 Load xib. NSBundle.mainBundle().loadNibNamed return Bool

First of all the method has not been changed in Swift 3.

loadNibNamed(_:owner:topLevelObjects:) has been introduced in macOS 10.8 and was present in all versions of Swift. However loadNibNamed(nibName:owner:options:) has been dropped in Swift 3.

The signature of the method is

func loadNibNamed(_ nibName: String, 
owner: Any?,
topLevelObjects: AutoreleasingUnsafeMutablePointer<NSArray>?) -> Bool

so you have to create an pointer to get the array of the views on return.

var topLevelObjects = NSArray()
if Bundle.main.loadNibNamed("CardView", owner: self, topLevelObjects: &topLevelObjects) {
let views = (topLevelObjects as Array).filter { $0 is NSView }
return views[0] as! NSView
}

Edit: I updated the answer to filter the NSView instance reliably.


In Swift 4 the syntax slightly changed and using first(where is more efficient:

var topLevelObjects : NSArray?
if Bundle.main.loadNibNamed(assistantNib, owner: self, topLevelObjects: &topLevelObjects) {
return topLevelObjects!.first(where: { $0 is NSView }) as? NSView
}

Can't accept/deny individual changes with git merge anymore, can only accent/deny all changes all at once

Solved the issue. Apparently VS Code forces its new "Git: Merge Editor" setting to be enabled by default. Even if you have your corresponding "Code Lens" settings enabled, they will be overridden if you have "Git: Merge Editor" enabled. Disabling that did the trick.

How can I selectively merge or pick changes from another branch in Git?

You use the cherry-pick command to get individual commits from one branch.

If the change(s) you want are not in individual commits, then use the method shown here to split the commit into individual commits. Roughly speaking, you use git rebase -i to get the original commit to edit, then git reset HEAD^ to selectively revert changes, then git commit to commit that bit as a new commit in the history.

There is another nice method here in Red Hat Magazine, where they use git add --patch or possibly git add --interactive which allows you to add just parts of a hunk, if you want to split different changes to an individual file (search in that page for "split").

Having split the changes, you can now cherry-pick just the ones you want.

git cherry-pick says ...38c74d is a merge but no -m option was given

The way a cherry-pick works is by taking the diff a changeset represents (the difference between the working tree at that point and the working tree of its parent), and applying it to your current branch.

So, if a commit has two or more parents, it also represents two or more diffs - which one should be applied?

You're trying to cherry pick fd9f578, which was a merge with two parents. So you need to tell the cherry-pick command which one against which the diff should be calculated, by using the -m option. For example, git cherry-pick -m 1 fd9f578 to use parent 1 as the base.

I can't say for sure for your particular situation, but using git merge instead of git cherry-pick is generally advisable. When you cherry-pick a merge commit, it collapses all the changes made in the parent you didn't specify to -m into that one commit. You lose all their history, and glom together all their diffs. Your call.

Is it possible in git to view who merged a branch if it was without a new commit?

It sounds like you have a scenario when one user is fast-forwarding the master branch from a feature, and in the process is bringing in commits which were done by another developer. There is no trail left behind of this, so it would appear that two developers made those commits, when in fact the fast-forward was done by a single developer.

There is a way to force a merge commit even when a fast-forward would occur, and a merge commit would not be required. If you were planning to merge feature into master, you could guarantee a merge commit by using the --no-ff flag:

git checkout master          # switch to master
git merge --no-ff feature # merge feature into master; force merge commit

Of course, if you are using something GitHub or Bitbucket, this merge might be taking place on the repository itself. In this case, you would have to configure your specific provider to do this.

Reference: Why does git fast-forward merges by default?



Related Topics



Leave a reply



Submit