Visualising a 'Smarties' lid using XAML (WPF/Silverlight, Visual Studio/Blend)

Posted by Mr. Disappointment on Stack Overflow See other posts from Stack Overflow or by Mr. Disappointment
Published on 2011-01-10T20:38:29Z Indexed on 2011/01/10 20:54 UTC
Read the original article Hit count: 268

Filed under:
|
|
|

Hi folks,

First off, to clarify something in the title which could well be ambiguous/misleading, I'd like to inform you of my definition of 'Smarties', as I know often products are available all over - only under a different alias. Smarties are a candy product in the UK, little chocolate drops covered in a crispy shell which are distributed in a card tube, this tube used to have a plastic lid/top with an individual letter on the underside (they've taken a more economical approach as of late), the lid/top of the old-style tube is the main element of this question.

Familiarisation Link

Lid View Link

Okay, now with the seller-type pitch out of the way (no, I don't work for Nestlé ;)), hopefully the question is becoming rather clear. Essentially, I'd like to recreate one of these lids using XAML, ultimately to be utilised in a Silverlight web application. That is, I'd like to result in a reusable control, of which the following is true:

  • It looks like a Smarties lid.

  • The colour can be specified.

  • The letter can be specified.

  • The control can be rotated to display either side.

The second two seem trivial, but we must bare in mind that the background colour specified will almost, if not always, be the same as the foreground, leaving a visibility issue where the character content is concerned; as for the rotation, I'm hoping this kind of functionality is reasonably available, and acceptable to implement.

So, to put this out there, consider a control named SmartiesLid which derives from ToggleButton (appropriate?) and further plotted out using a style in a resource dictionary which applies to it, as follows:

<Style TargetType="local:SmartiesLid">
    <Setter Property="Background" Value="Red"/>
    <Setter Property="Foreground" Value="Red"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:SmartiesLid">
                <Grid x:Name="LayoutRoot">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width=".05*"/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition Width=".05*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height=".05*"/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition Height=".05*"/>
                        <RowDefinition Height=".1*"/>
                    </Grid.RowDefinitions>                       
                    <Ellipse Grid.RowSpan="4" Grid.ColumnSpan="4" Fill="{TemplateBinding Background}" Stroke="Transparent"/>
                    <Ellipse Grid.RowSpan="2" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" Fill="{TemplateBinding Background}" Stroke="Transparent">
                        <Ellipse.Effect>
                            <DropShadowEffect Direction="280" ShadowDepth="6" BlurRadius="6"/>
                        </Ellipse.Effect>
                    </Ellipse>
                    <TextBlock Grid.RowSpan="2" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" 
                               Name="LetterTextBlock" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" FontSize="190"
                               HorizontalAlignment="Center" VerticalAlignment="Center">
                    </TextBlock>
                    <!--
                    <Path Stretch="Fill" Grid.Row="3" Grid.RowSpan="2" Grid.Column="1" Grid.ColumnSpan="2" Fill="Black" Data="...">
                        How to craw the lid 'tab'?
                    </Path>
                    -->
                </Grid>

                <ControlTemplate.Resources>
                    <TranslateTransform x:Key="IndentTransform" X="10" />
                    <RotateTransform x:Key="RotateTransform" Angle="0" />
                    <Storyboard x:Key="MouseOver">
                    </Storyboard>
                    <Storyboard x:Key="MouseLeave">
                    </Storyboard>
                </ControlTemplate.Resources>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOver}"/>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseLeave}"/>
                        </Trigger.ExitActions>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="true">
                        <Setter TargetName="LayoutRoot" Property="RenderTransform" Value="{StaticResource IndentTransform}"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter TargetName="LayoutRoot" Property="RenderTransform" Value="{StaticResource RotateTransform}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="Gray"/>
                        <Setter Property="Opacity" Value="0.5"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

With this in mind, can anyone give input on, in decreasing order of my incompetence in an area:

  • Designing the overall look and feel of the damn thing (I'm no designer, and while I could hack away at this single control for days and potentially get something relatively useful, it's always a gamble). The particular barrier for me here is 'pathing' the tab of the lid, as you will see in the XAML as an element commented out. Should Path be used, or would it be more appropriate to transform a rectangle with rounded corners, or any specific suggestions?

  • Bevelling the individually displayed letter; as detailed above, when the colour of both the foreground and background are the same then this will be invisible if no effects are applied, also for a decent level of realism I'd like to be able to apply such an effect/s. So far use of DropShadow and Balder3DEngine have fulfilled my requirements for graphics in XAML, how achievable is a bevel effect?

  • Rotating the control on mouse-click, that is, showing the opposing face. Is this going to be possible using a style and XAML only for the design? Or is it that ugliness may rear it's head in the form of code-behind to show/hide embedded controls? Should the faces be separate controls and later somehow combined?

  • Allowing the control to size dynamically. I'm supposing I will be able to convert a solid, absolute layout to a nice generic one when I actually have the former in place. Obviously this entails sizing the centralised letter and the lid 'tab', but that's it really, other than keeping the aspect ratio equal (since the ellipses grow nicely with the grid). Any suggestions to approaching this would be greatly appreciated, particularly with a dynamically growing font - I've done that before in a web-imaging scenario using code and System.Drawing, and wouldn't like to approach it in even a similar way.

By the way, the reason I specify both WPF and Silverlight is that, from my current knowledge, the inputs being written targeting either of these will be fairly transferable for similar output by the other, albeit not without alterations in either scenario. The resulting application is in fact destined to be written in Silverlight, however, so I don't fancy inviting anything from WPF which will guarantee my only being able to convert 90% of it.

I'll go give this little project a start, maybe in Blend(?), hopefully can catch up with some advice shortly. Thanks,

Mr. D

EDIT: Next question, ought this to be broken up into separate questions? :/

© Stack Overflow or respective owner

Related posts about wpf

Related posts about Silverlight