Sterling Code can help you get from design to finished HTML quickly.
We specialize in creating semantic, SEO optimized XHTML and HTML for rich emails. Offering competitive rates and quick turn-around, check us out!
Sterling Code can help you get from design to finished HTML quickly.
We specialize in creating semantic, SEO optimized XHTML and HTML for rich emails. Offering competitive rates and quick turn-around, check us out!
Yesterday we talked about how to make nifty selectable toolbars like this:
Now let's look at the finishing touch for our Preferences window; Animating the panel changes. We'll be flying through this at a pretty good clip, but don't worry. I'll provide the full source for your inspection.
First off, let's add some new outlets to our window controller:
ib_outlets :generalPrefsView,
:advancedPrefsView
Now in Interface Builder, we'll create the views for each preference pane by dragging Custom Views from the Library onto our Preferences.nib.
Note: Be sure to drop the Custom Views on the main nib window in IB, not on the Preferences NSWindow
. Your project (in IB) should look something like this:
Hook up the outlets to the new views, and edit your preference panels to your heart's desire. From here, we go back to the code.
Tip: Be sure to set the auto-sizing on your preference panels (the NSView
s) so that it matches the NSWindow
's contentView
.
Next up are some helper methods for our window controller. I won't spend too much time explaining these, but they're pretty straight forward.
def viewForTag(tag)
case tag
when 0: [@generalPrefsView, "General"]
when 1: [@advancedPrefsView, "Advanced"]
end
end
#viewForTag
actually returns our NSView
and a title string.
def newFrameForNewContentView(view)
newFrameRect = window.frameRectForContentRect(view.frame)
oldFrameRect = window.frame
newSize = newFrameRect.size
oldSize = oldFrameRect.size
frame = window.frame
frame.size = newSize
frame.origin.y = frame.origin.y - (newSize.height - oldSize.height)
frame
end
#newFrameForNewContentView
calculates the new frame rectangle for the window based on the new view (preference pane).
Now we're ready to fill out our selectPrefPanel
action:
ib_action :selectPrefPanel do |sender|
tag = sender.tag
view, title = self.viewForTag(tag)
previousView, prevTitle = self.viewForTag(@currentViewTag)
@currentViewTag = tag
newFrame = self.newFrameForNewContentView(view)
window.title = "#{title} Preferences"
# Using an animation grouping because we may be changing the duration
NSAnimationContext.beginGrouping
# Call the animator instead of the view / window directly
window.contentView.animator.replaceSubview_with(previousView, view)
window.animator.setFrame_display newFrame, true
NSAnimationContext.endGrouping
end
Right on! Now we setup the initial pane when the window loads:
def awakeFromNib
window.setContentSize @generalPrefsView.frame.size
window.contentView.addSubview @generalPrefsView
window.title = "General Preferences"
@currentViewTag = 0
# Will use CoreAnimation for the panel changes:
window.contentView.wantsLayer = true
end
That pretty much does it. Now you have a professional looking preferences window. So enough of those dang blasted NSTabView
s!
Here's the completed PreferencesController.rb. Or, you can download the full Xcode project. (Requires Leopard, Xcode 3, and Interface Builder 3)
Happy coding!
So you'd like to have some nifty selectable toolbar items to make your preferences window really polished? Or maybe you'd like to use the toolbar as a tab-set like Coda does. No problem, here's how to do it.
Note: I'm using Leopard & Interface Builder 3. You can create selectable toolbars in Tiger, but the process is different and not within the scope of this article.
To start, in the window controller, add an ib_action:
ib_action :selectPrefPaneldo|sender|# We'll do stuff here later...
end
Then in Interface Builder, create the toolbar and the toolbar items. For each toolbar item:
selectPrefPanel:
action on your window controller (probably the File's Owner)Before you save the Nib, be sure and set the toolbar's delegate
to the window controller.
Now back in the window controller code, implement a toolbarSelectableItemIdentifiers
method in your controller:
deftoolbarSelectableItemIdentifiers(toolbar)@toolbaridents||=begin
window.toolbar.toolbaritems.collect {|i| i.itemIdentifier }endend
Lastly, when the window loads, select the first toolbar item:
defawakeFromNib
window.toolbar.selectedItemIdentifier = window.toolbar.toolbarItems[0].itemIdentifier
end
Viola! Now you have selectable toolbar items.
Here's the full source for the window controller.
It's worth mentioning that this isn't specific to RubyCocoa. You can do the same thing in Objective-C, Python, or Nu (example).
Next, I'll show you how to create the views that will go within your preferences window, and how to animate them to really finish it off.
Update: Find the next article here.
Nuapp is a simple script (written in Nu, of course) that generates a skeleton Nu application. Check it out here: http://pastie.textmate.org/138976
You'll probably want to customize it. For instance, I doubt you'll want to use my "Requisite Beta Disclaimer". :-)
Here's a function I use in my Nukefile to compile XIBs into NIBs:
(functioncompile-xibs-from-to (xibs to_path)
(if (and (!= target "clobber") (!= target "clean"))
(then
(SH "mkdir -p #{to_path}")
((filelist xibs) each:(do (xib)
(set nib (xib stringByReplacingPathExtensionWith:"nib"))
(SH "ibtool #{xib} --compile #{to_path}/#{( nib fileName )}")))
(filelist "^#{to_path}/[^/]*.nib$"))
(elsenil))) (set @nib_files (compile-xibs-from-to "^resources/views/[^/]*.xib$""build/nibs"))
It uses ibtool
to compile the .xib into a .nib:
ibtool source.xib --compile target.nib