On my recent vacation trip to India, I had some time to get back to my
old hobby of sketching and painting. A hobby that I discontinued back in 2009.
In fact I missed it so much that the feel of getting back to pencil and
paper was great. Photoshop and Illustrator can definitely help you make
some great illustrations but nothing can substitute the pure joy of
using simple materials for drawing.
In 2010, I have decided to allocate more time to sketching and
re-discover a new form of relaxation. To get my juices flowing, I am
referring to the book: Drawing The Head and Figure by Jack Hamm.
In my opinion this is an awesome book on Figure drawing and I just love
the illustrative guidance on drawing different parts of the body. Note
that this is not a beginner book on figure drawing. If you are curious
to expand your knowledge on drawing the human figure, I suggest getting
the book: Figure Drawing for Dummies.
Although it is a dummies book, it provides an excellent introduction to
the subject and inspires you to learn and draw more.
My Sketchbook
The following scans show a few sketches from my sketchbook.
Applying the rule of fifth’s for the head proportions. Each feature of the head is some ratio of the eye-width. 5 eye-widths represents the of the head.
The logo of the Windows maker …
Taking a shot at Manga style heads …
Some perspective drawing …
Sketching myself at the act of the sketching myself …
At my in-laws, this was the table where we used to have our meals. (Click image for a full-size view )
Finally, a depiction of a Hindu-deity that represents an incarnation
of four gods in one form: Govinda + Siva + Rama + Krishna. The mark on
the forehead, tall golden crown, and the lotus and conch to the side
represent Lord Govinda. The crescent moon on the crown, tiger skin
around the waist, Trident on the right hand and the snake around the
neck represent Lord Siva. The Bow on the left hand represents Lord Rama.
The violet skin and the flute represents Lord Krishna. This drawing is
an adaptation of a painting done by the famous Indian
illustrator: Bapu. (Click image for a full-size view )
I recently received a mail from Marshall Price, one of the readers of my
book WPF Control Development Unleashed, pointing at a bug in the sample from Chapter 8 (Virtualization). He had
made some changes to the sample code in order to delete items from the
StaggeredPanel. This caused a crash in the virtualized panel.
(StaggeredPanel from Chapter 8 – Virtualization)
StaggeredPanel derives from VirtualizingPanel and there is a particular
virtual method, OnItemsChanged, that was not implemented.
OnItemsChanged is called every time an item is
added/removed/moved/replaced in the source collection. When an item is
removed (the case for which the panel was crashing), the panel is
supposed to delete the UI container associated with the item. This
ensures that the internal data structures are in sync with the source
collection.
Providing the override for OnItemsChanged avoids the crash. Notice the
use of RemoveInternalChildRange to remove the associated UI
container(s).
If you have encountered this crash, please add this snippet to
StaggeredPanel.cs and you should be fine. Incidentally I also noticed
that loading StaggeredPanelTester.xaml in Expression Blend causes an
exception. To circumvent that, you need to add this line at the
beginning of the method: MeasureOverride, in StaggeredPanel.cs:
Wondering what would it look like if you built WPF controls using F# ?
If yes, head over to Matt’s blog where he has translated almost all of the examples in my book WPF Control Development Unleashed to F# ! He is even starting a CodePlex project to host the source code.
Kudos to Matt for starting the effort.
The time is finally ripe to start exploring WPF control development with F# :)
This post is inspired by an interesting idea sent by Bo Stilling, one of
the readers of my book.
It combines the ideas discussed in Chapter 4 “Custom Panels” and Chapter
7 “IScrollInfo” to create a panel that lays out the items about a
half-circle. When you scroll the panel, the items move about a
half-circle. I thought that was interesting because generally when you
scroll, the items always move vertically up/down. This panel creates a
distortion that makes the items move about a circle, as in the following
figure:
Before we dive into the details, lets look at a video of the panel in
action:
How was it built?
There are two core responsibilities of this panel:
Layout about the half-circle
Scrolling
The layout is achieved by using the standard polar equations of a circle. The panel
provides three dependency-properties that allows you to control the size
of the items (ItemWidth, ItemHeight) and the gap between the items
(ItemGap). We use these properties to spread the items about the circle.
The ItemGap property can be used to create a fan-in, fan-out kind of
effect with the items. It is not shown in the video but you can play
with the ItemGap slider to see it in action.
Since the items are supposed to be present about a half-circle we have a
condition that checks the angle of an item against the hard limits –90
and +90 (-Math.PI /2 and +Math.PI/2). Any item whose angle is outside of
this range is reduced to a zero-size Rect. This is just one way of
optimizing the panel. Ideally, we should convert this to a
VirtualizingPanel that removes the UI containers outside this
angle-range. For now, let’s leave it out.
The other responsibility of scrolling is achieved by using a
dependency-property called NavigationOffset. The NavigationOffset is a
double value that lies in the inclusive range [0, <# of Children -
1>]. When the NavigationOffset is 0, you are at the first item, which
is located in the center of the panel. When the NavigationOffset is <#
of Children - 1>, you are at the last item, which is again located at
the center of the panel.
Thus the NavigationOffset is an interpolated value that lies in the
range [0, # of Children – 1]. This works well with the concept of
scrolling since it is just an interpolation of the thumb between the
Minimum and Maximum values of the ScrollBar. Thus in XAML, we can
directly bind the ScrollBar.Value property to the
HalfCirclePanel.NavigationOffset, as shown below:
There is one more advantage of having a property like NavigationOffset:
animation! In fact that is how I do the snap-in animation in the video
above. I create a Storyboard that animates the NavigationOffset from the
current value to the snap-in value. I have a public method called
AnimateToOffset that does this job.
Once you download, run the FluidKit.Showcase project to see the panel
come to life!
Have an interesting idea ?
I had a great time building this Panel over the weekend. Thanks to Bo
for sending the idea. If you have any interesting ideas or would like to
get suggestions for developing your controls, please do send it my way
and I’ll try to come up with a solution that you find useful. Also it is
always fun to have a challenge for a weekend ;-)
I have always enjoyed 3D modeling. The kind of tools you use and kind of
thinking that is required is so different than my everyday job of
writing code. That shift in mindset is quite challenging and also
exciting. In fact, the only reason I keep coming back to 3D modeling is
for this aspect: the shift in thinking! Of all the 3D modeling tools
I’ve used so far, I like Cinema 4D (C4D), for its ease of use and the
speed with which I can bring my ideas to life. Once past the initial
learning curve, it is really refreshing and relaxing.
To flex my grey cells, I decided to convert the logo of the company I
work for into a 3D model. BTW, if you can name the company from its
logo, then you are either in the financial industry or my colleague ;).
The 3D model
Given the logo above, our first step is to visualize what it would look
like when converted into a 3D model. I can imagine the thick curvy line
to be a tubular structure with changing widths. The tube starts from the
left and expands in diameter as it takes the first dip. Once at the
bottom-most point, it jumps back up, reducing its diameter to the
original size. This dip and rise happens for two more times, ending at
the right. The three orange ellipses become three ellipsoids or in other
words: vertically stretched spheres. Thus the tube and ellipsoids define
the nature of our 3D model. Lets see how we can create it in C4D.
Modeling the tube
Lets start by modeling the tube. C4D gives a great tool called Loft
Nurbs, which allows you to stretch a skin over two or more splines. As
an example, consider these splines and the lofted object (figure taken
from the C4D manual):
In our case, we are dealing with circles of different diameters arranged
along the tube, something like below:
The red circles represent the different diameters at various positions
along the tube. If we now stretch the skin along these circles we will
have the tubular structure we are looking for. Putting all of these
circles in a Loft Nurbs object gives us the surface we want.
Modeling the heads
The next thing we will model is the head. Since all the heads are of the
same size, we can just model one and duplicate it twice. The head can be
modeled using the Lathe Nurbs object. The lathe nurbs revolves a spline
about the Y-axis to create a 3D surface. This is the most popular way to
model vases, chess pieces, etc. In our case we will use a simple curve,
like a half ellipse and use a lathe nurbs object on that. Here is the
spline and the revolved lathe object:
Now lets arrange the objects according to the logo, ie. placing the
heads above the dips of the tube and aligning the YZ-axis of the
objects.
Our final C4D object tree looks like the figure below. Note the use of
the Loft Nurbs that encloses the different circle-splines and the Lathe
Nurbs for the heads.
The final render
Its now time to make the final presentation, ie. convert the wireframes
and simple gouraud-shaded surfaces to something more natural. This is
the part I like the most, where I get to play with the attributes of the
materials. We will go for some nice glass and metal materials for the
tube and heads. Also we will introduce a Floor and Wall (which are just
Plane objects) to cast shadows and reflections. The Floor has a
reflective material and the Wall has a white matte material. After all
that setup, here is the final render in different camera angles:
The render itself looks pretty good so I am going to leave it at that.
If I were looking for more style, I would have brought this image into
Photoshop and touched up the lighting or added more effects. For now, I
am happy with these images.
[Update] If you have Cinema 4D on your system, you can download and
take a closer look at the project file.
The website for my upcoming book is finally online, which also means the
Source code is available for download ! Without further ado, here is the
link to the website:
If you look under the Downloads tab, you will see the link to the zip
containing the source.
To make it easier for browsing the samples, we have included a custom
WPF app called BookExplorer. It provides a nice master-detail view of
the examples, as shown in the figure below:
If you are reading the book on
Safari, you will
know that there are some bonus examples included. These examples have
been clearly marked with (BONUS) in the BookExplorer app.
Hope you find the examples and the book useful for your WPF
explorations! You can buy a ton of copies for your friends and family at
Amazon.
After much prodding from friends and readers of this blog, I have
decided to release the source of the little 3D engine I wrote a long
time back (here and
here).
The source is part of the FluidKit
project and located under the Controls/View3D folder, as shown below:
You can run the FluidKit.Showcase project and see the 3D engine in
action. Click + drag anywhere in the white space to rotate the camera.
For more information about the engine, make sure you read my earlier
posts, mentioned above.
Treemaps are space-filling
visualizations of hierarchical data. Each node in the Treemap is
represented as a rectangle, whose size depends on some attribute of the
data. For example, if I am representing the high-volume trades in a day,
I could have a Treemap that shows different sized rectangles based on
the volume of each trade. Larger rectangles will represent the large
trades and smaller rectangles, the not so large trades. The most popular
of the treemap implementations use a squarified treemap algorithm that
produces more squarish rectangles, resulting in better aspect ratios.
In my current SilverLight project we required a variety of features that
were not present in any of the online implementations. Features like
multi-level treemaps, zooming, progressive reveal of information,
selection events, filtering, dynamic views, etc were something we found
missing in existing implementations. We wanted a single control that had
all of these features. Instead of starting from scratch we took
inspiration from the following places:
TreeMapView is the custom control I built that has many of the features
mentioned earlier. Its built in SilverLight 3 and as expected does a lot
of stuff via data-binding. It uses Visual State Manager (VSM)
extensively for showing state changes and animating transitions. Some of
the common features include:
Multi-level hierarchies: It can represent multiple levels of
hierarchy, so you can visualize treemaps within treemaps! The figure
below shows three levels of treemaps. \
\
Fine grained styling: One can style the root nodes, internal nodes
and leaf nodes separately. It is very common to use a different style
for the root level nodes, since you want them to stand out when you
first see the map. Similarly, the leaf nodes require special visual
treatment which is supported.
Drill downs: It is impossible to show every level legibly in one view
but drill-downs make this easier. You can click and go deeper into the
hierarchy and see more detail as you drill in. This is the notion of
progressive reveal, which is taken care using special states. You can
style the progressive reveal using VSM, giving you have complete power
in choosing how and what to style and show (reveal).
Breadcrumb trail: The breadcrumb trail is useful when you are doing
drill downs. The TreeMapView publishes a list of items indicating the
path along a subtree. This path changes as you drill in/out. You can
style this path and provide navigation support for your drill downs.
Filters: When viewing large datasets, filters make it easier to hone
into the stuff you are interested. Again, the filtered state of the
treemap can by stylized using VSM. The figure below shows one possible
way of styling filtered items. Colored items are the ones that match the
criteria.
Dynamic views: A treemap sizes the boxes based on some attribute of
the data. You can change this attribute on the fly (by bindings) and see
different views of the data. Quickly switching between different views
gives you a better perspective of the kind of the data you are
visualizing.
Coloring the tiles: This is a primary requirement of any treemap
control. The color of a box indicates the weight of some attribute. You
have complete control over this using bindings and converters. You can
bind to the attribute you want to use for coloring the tile and use a
converter to provide the different colors.
Virtualization: As you start visualizing large datasets, you cannot
afford to create controls for every item. Virtualization helps in
reducing the number of controls and improves the performance for this
scenario. Since custom virtualization is not supported natively in
SilverLight, I had to write my own version based on my experience with
WPF. In principle it is similar to Deep Zoom.
Mouse hovers: Hovers can be styled using ToolTips
Selections: You can click a tile to select it, which automatically
updates the SelectedItem property and also raises the SelectionChanged
event. Selections can be styled via VSM.
Usage
The programming model is fairly straightforward and using it is also
simple. Here is a Xaml snippet that shows the usage:
The TreeMapView creates instances of TreeMapTile for each item in a
level. TreeMapTiles can contain child tiles to give you the nested view.
The ChildItemsSourceBinding property of the TreeMapView can be used
to create nested levels. SizeBinding is used to size the tiles and
ColorBinding determines the color of each tile. Typically you would
use the ColorBinding with a converter to map the data to a brush.
ItemStyle is the style used for leaf tiles. ContainerStyle is for
internal nodes and RootContainerStyle is for the top level tiles.
Video
Here is a quick video showing all of these features in action:
Attached Properties is a wonderful feature of WPF and I find myself
using it in a variety of scenarios. The most recent one has to do with
view-management and transitions. The app that I was building has many
visual parts that can be swapped out and replaced with something else.
Each part is actually a UserControl, also called the view. To make
things interesting, the actual swap happens with a transition, using the
TransitionPresenter from the FluidKit library.
Since there are many such areas in the UI, which have changeable views,
there are many TransitionPresenters that act as the containers for the
views. Swapping of the views typically happens via user interaction and
there is also an action that needs to get invoked whenever a view
changes. In the first iteration of my solution, I had some code-behind
which would do the view-swap and call an action when the transition
completed. It looked something like the snippet below.
1234567891011121314151617181920212223242526
privatevoidExecuteFlip(objectparameter){stringprevFace=(string)parameter;stringnextFace=string.Empty;if(prevFace=="Preferences"){_flipTransition.Rotation=Direction.RightToLeft;nextFace="Main";}elseif(prevFace=="Main"){_flipTransition.Rotation=Direction.LeftToRight;nextFace="Preferences";}EventHandlerhandler=null;handler=delegate{_transContainer.TransitionCompleted-=handler;/* Do some action */};_transContainer.TransitionCompleted+=handler;_transContainer.ApplyTransition(prevFace,nextFace);}
ExecuteFlip is called on some user-interaction, generally via a command
invoked on a button-click. Depending on the parameter (which is the
current view-name) I decide what should be the next view and also adjust
the transition to use. Before invoking the transition, I attach an
event-handler for the TransitionPresenter’s TransitionCompleted event.
This is needed to invoke some actions after the transition completes.
As you can see, for a UI that has many such TransitionPresenters, the
code-behind can get pretty repetitive and messy. It’s too much
duplication and can easily overwhelm anyone maintaining this code.
Fortunately, attached properties come to the rescue.
The need for a ViewManager
To simplify this process of invoking a transition, attaching to the
TransitionCompleted event and doing some post-transition action, I have
come up with the static ViewManager class that exposes a single attached
property called ViewName (of type string). Within the property changed
handler for this atttached property, I discover the parent
TransitionPresenter and cache in a Dictionary. The Dictionary is just a
map of view-name to TransitionPresenter. Here is the code that shows all
of these pieces.
privatestaticDictionary<string,TransitionPresenter>_mapper;publicstaticreadonlyDependencyPropertyViewNameProperty=DependencyProperty.RegisterAttached("ViewName",typeof(string),typeof(ViewManager),newPropertyMetadata(OnViewNameChanged));staticViewManager(){_mapper=newDictionary<string,TransitionPresenter>();}publicstaticvoidSetViewName(DependencyObjectd,stringname){d.SetValue(ViewNameProperty,name);}privatestaticvoidOnViewNameChanged(DependencyObjectd,DependencyPropertyChangedEventArgse){UserControlview=dasUserControl;if(view==null)thrownewArgumentException("The ViewManager.ViewName attached can only be used on a UserControl");stringviewName=(string)e.NewValue;if(string.IsNullOrEmpty(viewName))thrownewArgumentException("ViewName cannot be null or empty");view.Loaded+=FindTransitionPresenter;}privatestaticvoidFindTransitionPresenter(objectsender,RoutedEventArgse){UserControlview=(UserControl)sender;view.Loaded-=FindTransitionPresenter;DependencyObjectparent=VisualTreeHelper.GetParent(view);while(parent!=null&&!(parentisTransitionPresenter)){parent=VisualTreeHelper.GetParent(parent);}if(parent==null){thrownewException("Could not find a TransitionPresenter in the parent chain of view");}TransitionPresenterpresenter=(TransitionPresenter)parent;stringviewName=(string)view.GetValue(ViewNameProperty);_mapper.Add(viewName,presenter);}
The interesting part here is the fact that I hook into the view’s
(UserControl) Loaded event to discover the TransitionPresenter. The
Loaded event is fired when WPF has created the visual tree and run a
first pass of layout and rendering. Hooking into this event gives us a
safe way to navigate the visual tree. The actual discovery of the
TransitionPresenter happens in the FindTransitionPresenter method. This
method also adds the link between the view-name and the
TransitionPresenter and stores it in the map. At the end of this, we
have a way to know the TransitionPresenter, given the string view-name.
Time for transition
Before we can invoke the transition, we need to associate the ViewName
attached property to all of our views. Additionally these views need to
be nested inside a TransitionPresenter, since we check for that in the
FindTransitionPresenter method. Here is a snippet of adding this
attached property:
With that done, we are now in a position to actually invoke the
transitions and to do that we have the ViewManager.SwitchView method.
Since for a transition you need two views, SwitchView takes the
view-names as its parameters. We actually have three different overloads
of this method:
The first overload should be obvious, it does a simple transition
between the views and nothing more. The second overload gives you a
callback method that will be invoked once the transition is complete.
The last overload gives you the additional capability to configure your
TransitionPresenter before the transition happens. I have used this
overload to change the transition for some views. Now lets look at the
SwitchView method. I am just showing the third overload, as the other
two just call into it.
1234567891011121314151617181920212223242526
publicstaticvoidSwitchView(stringfromView,stringtoView,ActiononViewSwitchCompleted,Action<TransitionPresenter>configure){TransitionPresenterfromTP=_mapper[fromView];TransitionPresentertoTP=_mapper[toView];if(fromTP!=toTP)thrownewException("TransitionPresenters of From and To views don't match");EventHandlerhandler=null;handler=delegate{fromTP.TransitionCompleted-=handler;if(onViewSwitchCompleted!=null){onViewSwitchCompleted();}};fromTP.TransitionCompleted+=handler;if(configure!=null){configure(fromTP);}fromTP.ApplyTransition(fromView,toView);}
The code here checks if the two views share the same TransitionPresenter
and throws an exception otherwise. It then hooks into the
TransitionCompleted event and fires the callback when the transition
completes. It also calls the configure callback to do any pre-transition
configuration on the TransitionPresenter. You can see how the
boilerplate code from the first implementation is nicely wrapped up over
here.
Using the ViewManager
If you have already setup the ViewName attached properties, using the
ViewManager is as simple as calling SwitchView with the correct
view-names. If you have some action to be carried out at the end of the
transition, you can also pass in an Action delegate. I use the Action
delegate to set focus on some controls or set some UI properties. The
ExecuteFlip method that I mentioned earlier now looks like so:
1234567891011121314
privatevoidExecuteFlip(objectparameter){stringprevFace=(string)parameter;stringnextFace=prevFace=="Preferences"?"Main":"Preferences";ActiononSwitch=()=>{/* Do some action */};Action<TransitionPresenter>configure=(tp)=>{FlipTransitiont=(FlipTransition)tp.Transition;t.Rotation=prevFace=="Preferences"?Direction.RightToLeft:Direction.LeftToRight;};ViewManager.SwitchView(prevFace,nextFace,onSwitch,configure);}
Some Takeaways
One can argue that using strings for view-names is not type-safe and
should instead be enums. But then you limit yourself to a particular
enum-type and need to constantly update it as new views are added.
One way to have type safety would be to expose static string
constants on your App and use them instead.
You can also have some setup methods on the ViewManager to do any
global configuration. You could call this once your main window is
loaded. I use it to setup some default durations on all
TransitionPresenters.
One big advantage of the ViewManager is that a transition on any
part of the UI can be invoked from any other part of the UI. All I
need to know are the view-names that are involved in the transition
and just call ViewManager.SwitchView. Internally the correct
TransitionPresenter is determined and used for the transition. This
has been a great feature for me as there are some non-user-events
that cause transitions on some views.