I think I am a lot less interested in doing custom skins, than I am in learning something simple like laying out the basic structure of the application. The thing that is really confusing is that it appears you can't really do this with Interface Builder. Maybe its the name "Interface Builder" that is confusing me?
As an example (lets take something simple and very Apple standard like iTunes for instance - yes I know its Carbon - but it IS defining a UI standard). You can identify the key Views and layout as something like:
Code:
Window
Top Toolbar
Content
SplittableView
LeftView
Library Chooser Panel
Now Playing Panel
Splitter
RightView
Big Honking Fancy List Control
iTunes MiniStore
Bottom Status Bar
So how do you layout these basic elements, views, whatever you want to call them - in Interface Builder? How do you make a toolbar? How do you add a splitter to a view? How do you make an Image Button? Can you use vector graphic images for Image Buttons? These are the kind of basic principles that I am looking for in a tutorial - which I haven't found anywhere.
I am willing to start simple - however, Currency Converter is just a little too simple.
The apertures shell was written using WPF - a brand new framework from the bad-guys. WPF is a complete departure from the "typical" way windows or even Mac controls and drawing are usually done. There is no drawing "event loop" that you are part of. The drawing model is a retained drawing model, in which there is a logical object tree - which represents all things that are rendered in your window. Rendering happens automatically and is all done in HW (directX) - there are no pixels. You can't really even get to a pixel - weird, I know... Its kinda like if you integrated Quartz Composer tightly into the Cocoa UI process.
There is an abstraction layer in WPF that is not present in cocoa and or Windows forms. Controls in WPF are inherently "lookless". The part that defines how the control looks (is drawn) is defined in a template which is a "property" of the control - an actual property in the OO language sense - so you can actually data bind templates to the control if you want. So depending on the type of data for instance, the control can choose different templates - and thats really neat.
The UI is meant to be defined declaratively using an XML based language called XAML - though this more or less optional, as everything that can be done declaratively in XAML can also be done in Code. The XAML part is meant to make it easier to make it more friendly for the graphic artists types. So this brings up a good question...
Are .NIBs editable by hand? Is .NIB and XML format?
WPF Controls by default use a default template defined by the OS you are running on - so XP has different built-in templates than Vista for instance.
So to make a "hello" button, it would look something like:
Code:
<Button Content="Hello">
or in Code,
Code:
Button b = new Button();
b.Content = "Hello";
And this automatically uses the "default" template of your system.
The cool thing is that "Content" can be anything. So this actually does what you would expect:
Code:
<Button>
<Button.Content>
<Image Source="someImage.png"/>
</Button.Content>
</Button>
This would still use all of the "default" skins for button states (so the mouse-over, pushed state are defined by the OS - but the Content area of the button is drawn using an Image object.
To create a totally custom button with custom states and behaviors, you would define a template for the button and assign it to the Button object like so:
Code:
<ControlTemplate x:Name="MyCustomButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Image Source="image.png" Grid.Column="0"/>
<ContentPresenter Grid.Column="1"/>
</Grid>
</ControTemplage>
Basically, this is a Button which displays two items side by side. One item is hardwired Image - and the other is a special display type which basically is mapped to the content property of the button.
The weird "*" width stuff specifies that the second column is always 2x the size of the first column - based on the size of the grid.
and to use this template in a button would look something like:
<Button Template="{DynamicResource MyCustomButton}" Content="I am a Combo Button"/>
WPF also has a concept of containers - very similar to Cocoa's NSView. In WPF these are called Panels. One of the really cool things in WPF are the different "Layout" panels that are included. Basically, there is a nice collection of Panel subclasses which handle any kind of layout situation you can dream of. The Canvas panel is the one most familiar to normal layout systems - basically allows its children to specify left and top properties in a cartesian coordinate system.
There are other more interesting panels however, which do a lot of layout work for you. Examples include:
- Grid - Similar to HTML Table element
- DockPanel - Allows you to specify children to be justified to top, bottom, right, left and has a neat option to auto size its last child. This was used a lot in my aperture layout.
- StackPanel - automatically stacks its children either vertically or horizontally
- WrapPanel - similar to StackPanel but Auto-Wraps children at boundary
Panels can contain other panels as well as controls, and elementary image and graphic objects. Most panels can contain multiple children, one exception is the Border Panel - however you can simply use a mult-child panel as the child of the border if you want it to contain multiple items. The Border panel is really powerful though, as it has stroke, fill, and "corner radius" properties which allow you to easily do nice rounded-rectangle interfaces - it was used a lot in my Aperture shell.
One of the truly powerful things about WPF Panels - which is what allows such flexible "skinning" - is that all Panels have Background and Opacity Mask properties and these can be any host of powerful brushes, such as solid color, gradient, tiled image, or even a visual "snapshot" of any other panel. So you can "paint" if you will, the background of a Panel with the output of any other panel. The layout tool (called Blend) also makes it easy to adjust things like background colors, gradients, and such.
Ok, two closing items...
I feel I am guilty of coming across pro-microshaft... believe me it is not what I was intending - though to be honest, WPF as an architecture is f*n elegant. I would highly suggest at least researching it to learn about a different way of approaching UIs - which is obviously my primary interest.
My honest intentions were to figure out how to go about learning to think like a cocoa developer when you have been trained for so long to think in a declarative, object oriented way.
Also, please do not confuse WPF with WPF/E (or Silverlight) - as these are two TOTALLY different Microsoft technologies. WPF is a desktop application framework - though the managed code part does get in its way... WPF/E or Silverlight is ms's "internet" plugin meant to compete with Flash. Even though the names are similar, and there is some overlap in some areas, they are not the same thing at all - Silverlight lacks all of the features that makes WPF cool, like panels, data binding, and Control Templates. And not to mention it is dependent on Javascript...Uhg! Woops, I think I said previously, I would not get into language debates...
I guess what I am really looking for, are really good Cocoa tutorials. If I had the time and the $$$$, I would go to Big Nerd Ranch - heck I grew up in the south and need me some vacation time, but for now I am stuck in Brooklyn, NY... looking to find the best Mac programming community I can find on the interweb...
cheers!