Friday 22 April 2011

In-Traction

My head has been hurting of late. As well as continuing to plug away at WPF, doing fun stuff like creating optimised vector graphics editors and custom controls, I am having to develop in XNA and Silverlight for Windows Phone 7, Objective-C and Cocoa for iPhone and somehow find room to at least keep abreast of Android and Java. Ouch!

It strikes me there are just too many devices, platforms and API's out there. Luckily I have some great people working with me and I can at least leave HTML5 and Android alone...for now.

In other news, DiceBox RPG has been doing really well. Its just a shame we can't make it's counterpart (DiceBox) free on the app store. If Microsoft would only get its act in gear and let its developers in the UK ad support their apps... Oh well, sure we wont have to wait too much longer.

Anyhow. I now find myself well and truly in the mobile arena and I'm not sure how much longer this blog has left in it. I guess you never know, I may well end up doing some GIS stuff again at some point but, outside of mobile, that is looking increasingly unlikely.

Having said that, a new and interesting blogging effort is underway. If you are at all interested in smartphones, tablets and the future of computing then why not pop in on the new site at www.in-traction.com

See you there.

Saturday 22 January 2011

An Expression Blend TabControl Style

After spending some time trawling the web and failing to find the style I was after, I decided to sit down and put one together myself.

A couple of hours later, and with a bit of help from Snoop, this is what I came up with; It’s a style for a tab control and, in-particular, a tab item, that goes some way to looking and feeling like the one used by Expression Blend.


The tabs are prevented from rearranging themselves into multiple lines by swapping out the TabPanel with a StackPanel.

To more closely resemble the style adopted by Blend the TabPanel could instead be replaced with the SqueezeTabPanel, which can be found on CodeProject. For the time being, this has been left as an exercise for the reader ;)

XAML:
 <Style TargetType="{x:Type TabControl}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid KeyboardNavigation.TabNavigation="Local">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel
Orientation="Horizontal"
Name="HeaderPanel"
Grid.Row="0"
Panel.ZIndex="1"
Margin="0,0,4,-1"
IsItemsHost="True"
KeyboardNavigation.TabIndex="1"
Background="Transparent" />
<Border
Name="Border"
Grid.Row="1"
Background="LightGray"
CornerRadius="2"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2" >
<ContentPresenter
Name="PART_SelectedContentHost"
Margin="4"
ContentSource="SelectedContent" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="#888888" />
<Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Path
x:Name="Cross"
Data="M0,0L6,6 M6,0L0,6z"
Stroke="LightGray"
StrokeThickness="1.7"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Cross" Property="Stroke" Value="White"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Cross" Property="Stroke" Value="LightGray"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Margin="0,0,-12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<Border
x:Name="Border"
Grid.Column="0"
Grid.ColumnSpan="2"
CornerRadius="3,0,0,0"
Background="#FF333333" />
<Path
x:Name="RoundedCorner"
Grid.Column="2"
Stretch="Fill"
Data="M6.5,2.6C4.767,0.973 2.509,0 0,0 0,0 0,19 0,19L23,19z"
Fill="#FF333333" />
<Button
x:Name="CloseButton"
Grid.Column="1"
Visibility="Collapsed"
Margin="0,0,0,0"
Width="6"
Height="6"/>
<ContentPresenter
x:Name="ContentSite"
TextElement.Foreground="White"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100" />
<Setter TargetName="Border" Property="Background" Value="Gray" />
<Setter TargetName="RoundedCorner" Property="Fill" Value="Gray" />
<Setter TargetName="CloseButton" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="#EEEEEE" />
<Setter TargetName="RoundedCorner" Property="Fill" Value="#EEEEEE" />
<Setter Property="Foreground" Value="#888888" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>