NSToolbar can have two sizes controlled by the user using "Use Small Size" menu item. Regular toolbar size requires 32x32 icon sizes for each item while small size uses 24x24. I don't want icons to scale by default since i have a pair of icons for each toolbar size. Instead i want icons to automatically switch to the other size when user changes toolbar size.
Now IB only has a single image field for each toolbar item. Is there a way to automatically change icon size or do i have to subclass NSToolbar and react to size changes manually and fix the icons for each item?
From the Apple Guide for toolbars:
You should provide image representations specific to the default, regular and small size modes in a single image that supports multiple image representations such as icns or tiff. The appropriate image representation is automatically displayed for the toolbar's current sizeMode. If an appropriate representation is not available, the toolbar scales the a representation to the appropriate size for the current mode, at a cost in performance and appearance.
Wrong way to approach the problem. NSToolbar does not provide any way to interact with the Toolbar before and/or after the change of toolbar size.
Perhaps, you can solve the problem subclassing the NSToolbarItem and overriding the method:
- (void)setMinSize:(NSSize)size
Something like the following should be fine for your problem.
- (void)setMinSize:(NSSize)size {
NSLog(#"setMinSize: %#", NSStringFromSize(size));
if(size.height < 32.0) { //if we're resizing to min_size than apply a new image based on the actualIdentifier
if([[self itemIdentifier] isEqual:#"effectsButton"]) {
[self setImage:[NSImage imageNamed:#"effectsButton24"]];
}
} else { //else switch back to the standard image
if([[self itemIdentifier] isEqual:#"effectsButton"]) {
[self setImage:[NSImage imageNamed:#"effectButton"]];
}
}
[super setMinSize:size];
}
Simply check if the new size is small (<32.0). If this is the case, you set a new image for each NSToolbarItem basing on the identifier provided.
Related
I'm trying to create an NSToolbar with items similar to the Apple's Mail app on macOS. I have an issue with the default toolbar item's width though, as it seems to be inconsistent. Since Big Sur, the items are meant to be sized automatically by AppKit and the NSToolbarItem minSize, maxSize properties have been deprecated.
I'm setting the image property for each NSToolbarItem, not using custom views. As you can see in the screenshots below, the envelope icon has a different "highlight" area (less padding on the sides) while the trash icon has a much larger highlight area.
The envelope icon is a single NSToolbarItem while the archive box and trash items are displayed using NSToolbarItemGroup with NSSegmentedControl view.
In the Apple's Mail app, even single toolbar items have the same width as the grouped items:
How to increase the toolbar item's width when using an image instead of custom view?
Deprecating a property and leaving you in the dark how to achieve a until recently simple effect without using the deprecated property is typical for how Apple deals with AppKit nowadays.
I would not be surprised of the Mail app still uses the deprecated minSize property, or that the NSToolbarItem objects are based on NSButton views with a minimum width NSLayoutConstraint (which is my current solution).
To continue using minSize without deprecation warnings, you can consider to use a simple ToolbarItem class like this:
class ToolbarItem: NSToolbarItem {
override var minSize: NSSize {
get {
return NSSize(width: 50, height: 30)
}
set {}
}
}
I'm making an app that is modeled after the Sketch example program. I've rewritten Sketch in swift (it was a great way to learn the language) and everything works fine.
However, in this app, I want the document to be fixed size, different from the default size used by Sketch. So I set the size I want in Interface Builder on the Window and on the custom NSView within the ZoomingScrollView. I also set a fixed minimum and maximum on the Window to the same values and unchecked resizable.
The app opens with the window the correct size, but the document canvas is still the original size from the Sketch app. My window is wide and squat (landscape) and the document inside of it is tall (the vertical scroller is active) and narrow (there is a gray void area to the right of the document canvas).
I tried programmatically resizing the custom NSView but nothing happens. In fact, custom NSView is happily reporting that it's bounds and size are the fixed size that they should be.
override func awakeFromNib() {
var f = self.frame; // If you set a breakpoint here f reports as 568x320 anyway
f.size.width = 568;
f.size.height = 320;
self.frame = f;
self.setFrameSize(f.size)
self.setBoundsSize(f.size)
}
One hint, I think, is that the Sketch app itself does not change canvas when you try to resize it's window and if you change it's window and SKTGraphicView sizes in Interface Builder, you get the exact same behavior that I'm seeing.
I feel like I'm missing something very basic here!
I like to try to completely take over the area where the NSToolbar resides so I can put my own custom controls, views and background. The advantages of using this area are:
Any sliding panels appear below the toolbar area instead of just the title bar.
In Lion, the toolbar area comes down along with the menu bar when the mouse is at the top of the screen.
I have tried using a borderless window, and implementing my own custom views within it but unfortunately I lose the above advantages as well as having a few other minor problems.
My current method is to use the undocumented method '_toolbarView' with the NSToolbar and add my custom view into its subviews. This works fine as I can turn off toolbar customisation. Unfortunately, the size of the toolbar is initialised with the items within that toolbar. Does anyone know if I can change the size of toolbar without adding a fake ToolbarItem?
Maybe there's also a better way of doing this that I am currently unaware of.
Thanks for any suggestions and comments.
No need to use any undocumented APIs. Just create a toolbar item with a custom view:
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];
…
[item setView:myCustomToolbarView];
…
}
You can control your custom toolbar’s size using the item’s minSize and maxSize properties (e. g. in your NSWindowDelegate’s -windowDidResize:).
Remember to also update the toolbar display mode so it doesn't show item labels:
[toolbar setDisplayMode: NSToolbarDisplayModeIconOnly];
So I'm using the method:
[someWindow setContentBorderThickness:24.0 forEdge:NSMaxYEdge];
But I can't seem to get the toolbar to increase in height. It simply stays the same as in default. Can anyone shed some light here?
An NSToolbar is automatically resized to accommodate the height of the tallest NSToolbarItem. The standard (large) toolbar items are all 32 px tall, so the toolbar has no need to make itself larger. If you do something like add a custom view toolbar item, then it will be resized to accommodate that item, as shown in the image below:
(To accomplish the result shown above, I clicked on the toolbar twice in IB to bring down the Allowed Toolbar Items sheet, then dragged an NSView custom view from the library palette onto that sheet).
P.S. I'd recommend using this capability with discretion.
You cannot specify an arbitrary height for NSToolbar. You can, however, specify a size mode. A toolbar with 24x24-pixel icons has a small size mode:
[toolbar setSizeMode: NSToolbarSizeModeSmall];
which is equivalent to Size: Small in Interface Builder’s Attributes Inspector.
By default, cocoa progress bars are slightly fat and I want something a little slimmer, like the progress bars seen in the Finder copy dialog. However, Interface Builder locks the NSProgressIndicator control height to 20 pixels and my programmatic attempts to slim down aren't working, as calls to
[progressBar setControlSize:NSMiniControlSize];
and
[progressBar setControlSize:NSSmallControlSize];
in awakeFromNib don't do anything, and the suggestive looking NSProgressIndicatorThickness seen in the header file doesn't seem to plug into any methods that I can see.
What's the trick?
Those calls should have worked. In Interface Builder, in the Geometry pane (the one whose icon is a ruler), there is an equivalent control size selector that offers "Regular" and "Small" sizes.
in IB
select your NSProgressIndicator control
in the utilities view select the View Effects inspector
press + in Content Filters
select Lanczos Scale Transform filter
set the appropriate scale value in the Scale row
set the Aspect Ratio too if you need to change the height only