Disable user interaction for NSImageView - cocoa

I have 2 sets of images. One set contains draggable ones and other is a static set. I have implemented drag-drop functionality for the draggable images. This is because the images needs to be dragged to static ones which contains matches. Now after placing the dragged image on the static one, there is nothing to do with it, hence I want to disable user interaction for image (since it's still draggable).
I have explored several solutions and SO questions here and there , but none of the solutions helped!
Can some one please help me how to remove dragging or user interaction for NSImageView?
Thanks everyone in advance :)

Create custom class of NSImageView and implement mouse entered and mouse exit method with empty definition

The easiest solution in my opinion is subclassing NSView. Your custom view should just contain an image variable you want to draw inside. After that you can use your custom view instead of default NSImageView, it will pass mouse events through.
Example:
class ImageView: NSView {
var image: NSImage?
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
if let image = image {
image.draw(in: bounds)
}
}
}
Be noted that the target image will be scaled non-proportionally to your ImageView instance size.

Related

Cocoa: Setting Mac window full screen the view doesn't change size

I'm setting up window to be able to be full screen:
class WindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
window?.titleVisibility = .hidden
window?.collectionBehavior = [.fullScreenPrimary]
}
}
And the window works fine but the view doesn't go full screen
any of you knows what I need to do to set the view full screen as well as the window?
I'll really appreciate your help.
I assume your problem is not related to the window setup.
You must use layout constrains or classical springs and struts to layout and automatically resize your view dependent on the window content view size.
You can set all this options comfortable in Interface builder.
Constrains approach:
Springs and struts:
Basic window configuration can be done in Interface builder as well.
Best wishes.

NSWindow launching with wrong size after setting contentViewController to NSTabViewController

I have an Xcode project with an NSWindowController whose contentViewController was set to a subclass of NSViewController. I recently removed the NSViewController subclass from the storyboard and replaced the contentViewController with an NSTabViewController subclass.
Now, when I run the application, the NSWindow opens with a size of 500x500 instead of the size of the first tab. What's more, there is no view I can see in the storyboard that has a size of 500x500, and that size isn't being programmatically, either. The window itself is set to a different size, as is the view in the NSTabViewController's first NSViewController.
I'm assuming that there is some sort of constraint I have to set somewhere, but if there is, I don't know where/how to find it. Using Xcode 9.2 and High Sierra.
Programmatically setting the window's size to the correct size in windowDidLoad() works, but if I ever change the size of the view, I'll have to change that, as well, which will get old, quick.
Sorry if this is vague; I genuinely have no clue what kind of screenshot or code snippet would be helpful.
I recently ran into this frustrating problem as well.
There are a couple options to workaround this problem:
As you mentioned, set preferredContentSize in each of your custom view controllers that hold the tab's content to your desired size. This is inflexible but it does work.
// Swift
class FooViewController: ViewController {
override func viewWillAppear() {
super.viewWillAppear()
preferredContentSize = NSSize(width: 400, height: 280)
}
}
I found a hint to a better solution in this SO answer. You can add a subview (stackview, nsview, etc...) to the main view of the view controller that handles the tab's content (phew!) and then add constraints that pin it to each edge and add constraints that set the size.
Here's a screenshot of what it looks like in Interface Builder. I added a Stack View and then added 6 constraints.
Hope this helps.
Joshua's answer with setting the preferredContentSize did the trick, all kudos to him! One remark worth making is that since this is done exclusively for the parent tab view controller it's a good idea to subclass it and move this handling into tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?) delegate method, which gets invoked when the tab is selected:
override func tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?) {
tabViewItem?.viewController?.preferredContentSize = tabViewItem?.view?.frame.size
// Alternatively: tabViewItem?.viewController?.preferredContentSize = tabViewItem?.view?.fittingSize
super.tabView(tabView, didSelect: tabViewItem)
}
This way the preferred content size is always up to date and you can worry not about manually refreshing it, assuming the view provides the correct frame size or fitting size, which is easily achieved with constraints.
This method also get's invoked after the window controller finishes loading and where the 500×500 gets initially set.
Setting the preferred content size in every tabbed view controller itself is not ideal: the same code is duplicated across multiple controllers and adds unnecessary noise if these controllers are reused else where.
I had a similar issue. I added a view controller with a container view as the window content and pointed the container view content to the tab view controller.

Scroll view with a dynamic height in Swift

I am having trouble understanding how to embed my view into a scroll view with a dynamic height. I have managed to create scroll views before, but only with a static height. How would an iPhone application, such as Facebook or Instagram, for example, manage to create a scroll view for an entire feed of dynamic-height data. To this point I have used storyboards to create the scroll views, but I am assuming that this done in code would be much better.
class connectDetailsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//set up variables with data
fillData()
}
override func viewWillAppear(animated: Bool) {
let nameTitleString = String(businesses[businessNum]["name"]!)
nameTitle.text = nameTitleString
processTimes() // Adds information for the hours of operation, if applicable
processDetails() //Adds information for the details if possible (a few sentences to a few paragraphs)
}
}
processDetails() and ProcessTimes() will edit the content in a stack view, how can I create a scroll view to encompass both of these stack views at the correct height?
Generally, for providing a feed of content such as a Facebook timeline you would likely use a UITableView as it manages the reuse of cells and the overall contentSize internally using it's delegate methods on the dataset to determine number of rows, estimated row heights and so on. The tableView actually uses a scrollView to acheive this but it handles it internally.
In my opinion this would be your best approach, to do this without using a tableView you would need to replicate alot of the logic that it performs on your behalf.
The main thing to remember with a scrollView is that it can load content that is larger than the scrollView, and then manages scrolling/panning/zooming to allow you to view the larger content.
If you just wanted to know how to do this yourself, you would likely need a parent container in the scrollview and then you would keep adding new views into it, adjusting the scrollViews contentSize height each time you add new content

Unexpected NSTextField background color, should be transparent

UPDATE:
I've added a sample project for testing, see at the bottom of the post.
ORIGINAL QUESTION:
I've got an NSWindow and I change its background when some other parameters change.
The window background is a gradient I'm drawing by overriding drawRect in a subclass of the window's view.
class MainWindowView: NSView {
override func drawRect(dirtyRect: NSRect) {
var rect = dirtyRect
let gradient = NSGradient(startingColor: backgroundColor, endingColor: darkerBackgroundColor)
gradient.drawInRect(rect, relativeCenterPosition: NSPoint(x: 0, y: 0))
super.drawRect(rect)
}
}
And I've got two NSTextFields on this window.
The NSTextFields are both set to drawsBackground = false in awakeFromNib and set to borderless in IB.
I'm not using NSAttributedStrings here, only changing the stringValue of the NSTextFields, and of course their textColor.
Everything is working... except that sometimes, the text fields have an unexpected slightly dark semi-transparent background.
(It's hard to see on some screens but it's there.)
Question: why does this darker background appear?
And of course: what could I do to fix it?
I'm pretty sure it's the gradient that breaks something but I can't find what...
Note: the project is in Swift but I can read an Objective-C answer.
EDIT:
So indeed it seems to be coming from the gradient that's behind, see this other screenshot from a test window. This time the gradient is drawn in a Custom View under an NSTextView, and the same undesired effect happens: parts of the text field background are visible but shouldn't.
UPDATE:
I have made a very simple example in a project for testing, with a gradient that shows the phenomenon more visibly. There's only a window, my gradient class and a text field. You can get it (30ko only) in this ZIP file.
You always draw the gradient in the dirty rect. When the text changes, that rect is only the size of the textfield, not of the whole view. Your drawRect function then draws the full gradient in the textfield's background rect, rather than just the portion of the background-view-wide gradient you'd see through the textfield.
If you redraw using your view's frame, and ignore the dirty rect argument, you should get the desired appearance.
I'm guessing your text field isn't layer-backed. If not, turn on layers (in IB or via -wantsLayer for the view in code) for at least the text field. If that alone doesn't work, try turning on layers for the gradient-hosting view as well.

How to use UIVibrancyEffect (iOS 8) for a Label within a UITableViewCell

I have watched WWDC2014 and wanted to try the UIVibrancyEffect right away, I have succeed in using UIBlurEffect. However, the Vibrancy Effect confused me a lot as it requires to use with UIBlurEffectView.
Here is the hierarchy:
Root View (UIView) (I have set backgroundColor to a image)
(Inserted a Blur View By Code)
UITableView
UITableViewCell (Custom)
UILabel <--- want to apply here ^.^
I have the above in my storyboard.
I have changed the Root View Background with a image, and added UIBlurEffectView, I want to apply UIVibrancyEffect to my Label in the UITableViewCell.
Please kindly give advice.

Resources