ItemSkimmingPanel - a panel that does more than just layout
Recently Apple released their next version of iLife, which has some cool enhancements to iPhoto and iMovie. One specific enhancement called “skimming” was interesting from my project’s perspective. The idea is that when you scrub your mouse over an album, it skims through all the photos in that album. The same interaction applies when you scrub your mouse over a movie clip: it skims through all of its frames.
We had a similar requirement for viewing all the items inside a container. Skimming looked like a neat way of doing that. We had a couple of different ways of implementing this interaction but finally we decided on making this interaction as a Panel. The justification can be summarized in the bullets below:
- Panel has a SetZIndex() API that is used to pop items to the front. This is useful to bring an item to the top of the stack.
- Panels can be used in conjunction with ItemsControlto leverage data-binding. This can be done by setting the ItemsPanelproperty of ItemsControl
We added an extra feature to skimming, which we call “Item Context”. When you are skimming through a bunch of items, you would also want to know where the item is positioned in relation to others. In other words you would want to know the context of the item relative to others. It is also very handy to quickly visualize your stack (aka container). Thus from a top level we have two different concepts in our ItemSkimmingPanel:
- It skims through all the items in the Panel when you scrub your mouse on it. Each “skimming” action brings the item to the top of the stack.
- When you start the skimming process, a context is also displayed to see the relative location of the item.
Both of these ideas can be seen in the video below. In the first half of the video you can see the skimming action without the context. The second half shows the context as you skim through the items. It will be clear how effective the skimming can be when the context is displayed.
A quick note on internals
The ItemSkimmingPanel leverages the fact that a Panel can automatically handle the ZIndex of an item. We listen to standard mouse events (MouseDown, MouseUp, MouseMove) to achieve the effect of scrubbing. To prevent very rapid scrubs we make sure that the mouse moves a specific distance between each scrub. The context for skimming is shown using Adorners. The Adorner is positioned relative to the panel that is being scrubbed. Skinning of the context is supported via ControlTemplates. There are two Dependency properties on ItemSkimmingPanel used specifically for this purpose: ContextContainerTemplate and ContextItemTemplate. The names should be self-explanatory.
All of the skimming and context display logic is nicely encapsulated inside the ItemSkimmingPanel.