Setting the position/width of an NSSlider inside an NSMenuItem - objective-c

I've got an NSMenu attached to an NSStatusItem, and inside that NSMenu I have a NSMenuItem for which I've set the view property to an NSSlider object. That works (it got me what I was after) almost.
The result looks like this:
NSSlider in an NSMenu as an NSMenuItem.view http://dl.dropbox.com/u/91596/Screenshots/k8tl.png
The problem is that I'd like the slider to line up with the menu items above it, so it doesn't look so friggin terrible.
I can't find anything in the apple documentation that says anything about being able to set the position of an NSSlider so I assume I'm going to have to wing it by drawing it myself.
Is that a correct assumption? If so, what are some class references/suggested reading links for achieving that result? Or, am I going about this wrong?
While I'm at it - I had to drag the slider in the UI builder to the desired width I wanted - is there any way to programmatically set the width of the slider so it fills up the desired space inside the menu?
Thanks, sorry of these are noob questions - I'm pretty new to ObjC programming.

First make your own NSView. Next, put your NSSlider in that view. If you need special spacing, adjust the slider in the container view. Or, maybe, twiddle in Interface Builder.

Related

Replacing NSTextField with NSScrollView to get a scrollbar

My OS X app written in Objective-C needs to display a varying NSString* variable theString which can get quite large.
I use Xcode IB to build a nib file which displays theString in a NSTextField* object panel declared inside AppDelegate.h like this:
#property (weak) IBOutlet NSTextField *panel;
Now I can set the contents of panel inside AppDelegate.m like this:
self.panel.stringValue = theString;
This all works fine. But I now want to give my text field a scrollbar. So in place of a "Text Field" I choose a "Text View" from the Object Library, and get its blue line to generate me a new declaration of panel which now looks like this:
#property (weak) IBOutlet NSScrollView *panel;
This now no longer works:
self.panel.stringValue = theString;
raising the error: (!) Property 'stringValue' not found on object of type 'NSScrollView*'
How do I need to fixup this statement?
(Might I just say I find the extensive Apple documentation on the topic byzantine and opaque. Why am I being naive to expect a simple answer to this simple question, as it all seems to imply? I must be missing something obvious -- what is it?)
What you got was a NSTextView wrapped inside a NSScrollView. The scrollView is the thing that makes the scrollbars you want. It basically holds a potentially much larger view inside its viewport and shows only small part of it, that you can shift around with the scroll bars. You need to get (another) reference from your code to the NSTextView inside the scrollView. You can find the NSTextView in the hierarchy in IB and attach to that.
This is in the direction of what you want but I think not quite what you need. The textView is a far more advanced control than a simple textField and probably more than you need. You could instead use a custom view by taking a NSScrollView that comes with a default NSView wrapped inside. Then instead of the NSTextView place your NSTextField on the NSView. The issue with this is that then you need to add some code to auto-resize the NSTextField and NSView based on the content of the textField. Once you got that sorted the scrollView will automatically arrange for the scrollbars that you need.

How to create a custom NSSlider with a transparent middle bar and custom knob size

I've searched around for some code on NSSliderCell but I can't find a way to do what I'm looking for.
I'd like to create something like this (where the white line is the slider knob, 1 pixel width):
I'm going to use this for the time bar of a music track, so it's going to move every second (that's why I want to use a NSSlider to make things easy).
What do I need to do to make a slider, with a transparent middle bar, similar to the image above?
PS: It's not going to be touchable, it's just for display.
You can just override drawRect:, as when subclassing NSView, except in your implementation, use [self doubleValue] to determine where to draw the line. However, I don't see the point of subclassing NSSlider in this case. A custom NSView could have a property that determines where to draw the line, and then other code could set that property or bind to it.
That looks like a vertical split view to me with a 1 pixel wide divider. You might try that. There's a method to set the position of the divider so it would be easy to move as you need. And you can make the divider 1 pixel by creating a subclass of NSSplitview and overriding the dividerThickness method to return 1. Then you just set the background of the 2 subviews to black and there you go. It's easy to try so maybe it will work for you. Good luck.
I finally got it:
I created a NSSliderCell subclass with a property #property float x;
I overrode the drawKnob method and inside it I wrote:
-(void)drawKnob:(NSRect)knobRect{ self.x = knobRect.origin.x; }
I dragged a NSSlider into my window (made it small, changed it's width to the window's width) and changed it's cell class to the one I created;
And then when the music is playing, every time a second goes by I do:
[_timeBarSlider setMinValue:0];
[_timeBarSlider setMaxValue:myTrack.duration];
[_timeBarSlider setDoubleValue:myPlayer.currentPosition];
[[_timeBarImageView animator] setFrame:NSMakeRect(_timeBarSliderCell.x, yourYCoordinate, yourWidth, yourHeight)];
_timerBarSlider is the NSSlider I have in IB / _timerBarImageView is the image view that contains the vertical image line / _timerBarSlderCell is the NSSlider's cell (subclassed)
PS: the NSSlider is behind every object in that window, so that the user can't see it. You can't setHidden:YES on it because the drawKnob method will not be called.

NSButton draw alternate image on click

I know this is probably super easy, but I'm having a hard time wading through header files and could use some guidance.
I have an NSPopUpButton defined in a nib with a menu attached to it. I have defined it in the nib to be "Pull Down" type with no arrow (the images given to me by our designer include a special arrow he wants to use). It is a borderless button. The title properly is empty, though I have set the image and alternateImage.
What I'm looking for is a configuration, either in the nib, file's owner implementation, or by subclass NSPopUpButton, that will allow me to display the button's alternate image (or any other image) while the button's menu is being displayed. Instead, it looks like the system is dimming the button's image.
I've tried numerous nib configurations, various properties of NSButton and NSButtonCell, overriding mouseDown and mouseUp. Nothing I do works.
If playing with the "Type" property doesn't help, you may well have to subclass the drawing of NSButtonCell to get what you want.
- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView in NSButtonCell seems promising.
I think it's custom NSButtonCell class time; I don't know of any way to override the theme for this type of button.
Your only alternative would be to use a regular NSButton with the appropriate image and show the menu at the correct position manually, which would probably be a lot easier to implement.

Add a second image to a custom UIButton

I've got an Custom UIButton. It's got
a "static" background image
a variable text (the Title) which gets set in the code
Now I would like to add an icon (UIImage/UIImageView) inside the button on the left of the text. (I use the indent to move the text slightly to the right). Is there an easy way of adding that icon (and referencing it from code, so I can change it) or would you recommend creating a completely new button e.g. based on a UIView? (e.g. a view, that responds to touches)?
I'm just trying to get a feel for what the best approach would be for this. Any experience?
Two ways:
I prefer doing this by subclassing a UIView and (as you mention) implement the UITouch-responder methods. You're also able to override drawRect: what I really like because it makes your app soooooo much faster!
Since UIButton is a subclass of UIView, you can add a UIImageView to your button by using addSubview:. If you save it in your main-class (#property (...) UIButton *button) you can always access it by calling [self button]. You can also subclass your UIButton and add this #property. That's up to you.
It's totally up to you. However I prefer the first way!

UILabel inside a UIToolbar using IB is invisible on run, how fix?

I want to show a total inside a toolbar. I put in IB the UILabel on top of the toolbar .
However, when I run the app, the UILabel is totally invisible (but can set values on code fine).
The most bizarre thing is that in other form, all work fine. I don't see why in one form work but not in another...
Any idea in how fix this? Or why is this behaviour happening?
Don't use a UILabel.
Use a UIBarButtonItem. Then set it to style: plain. It looks like a label, but it actually borderless button. This is the general practice of displaying text on a bar.
You can also create UIBarButtonItem with a custom view in code. You are simple "wrapping" the UILabel in a UIBarButtonItem allowing you to add anything you want to a tool bar.
To add in response to comment:
Either way, you make the button "inactive" and it doesn't respond to touches. Even though it is a button, it doesn't appear to be one. This is how Apple expects to add views to a toolbar/navbar as apposed to "float things on top of it". It violates no HIG guidelines, much the opposite, it is a reccomended design technique.
To stop the glow:
Create the button programmatically, make sure it is disabled, add it to the bar, it should then be disabled, but not dim.
In IB, have you tried to select the label and use the "Bring to Font" menu item (under Layout)? It seems like you are trying to do something pretty standard.
When you try to set values, is the label coming up as nil or at address 0x0? It's possible that the label is there, but its text cannot be set because its instance is faulty (not properly connected in IB to the IBOutlet).... Just put a breakpoint on the line where you are trying to set the value(s) for the label, and verify that the label variable is not nil (or 0x0). If it's not, try setting the text and verify on the next line that its text was set properly.
drag a UIButton into your UIToolBar. Then uncheck User Interaction Enables for this button.
Customize your UIButton so that it will look like a UILabel. Hope this will help you.