To close of this month, here are some programming quotes that made me laugh out loud :)
Programming is like sex: one mistake and you’re providing support for a lifetime.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live
The C programming language -- a language which combines the flexibility of assembly language with the power of assembly language.
Any fool can use a computer. Many do.
To iterate is human, to recurse divine.
In order to understand recursion, one must first understand recursion.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
Managing programmers is like herding cats.
Weeks of programming can save you hours of planning.
There are only two kinds of programming languages: those people always bitch about and those nobody uses.
The last good thing written in C was Franz Schubert's Symphony Number 9.
I’ve finally learned what ‘upward compatible’ means. It means we get to keep all our old mistakes
There are two major products that come out of Berkeley: LSD and UNIX. We don’t believe this to be a coincidence.
The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry.
No matter how slick the demo is in rehearsal, when you do it in front of a live audience, the probability of a flawless presentation is inversely proportional to the number of people watching, raised to the power of the amount of money involved.
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
Without requirements or design, programming is the art of adding bugs to an empty text file.
Deleted code is debugged code.
Software is like sex: it’s better when it’s free.
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning
If debugging is the process of removing software bugs, then programming must be the process of putting them in.
Software and cathedrals are much the same – first we build them, then we pray
I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone.
But it works on my machine!
donderdag 28 juli 2011
vrijdag 22 juli 2011
Create your own simple intellisense for .NET
I was playing around with the source code of STFUandCode to add a little intellisense and I thought it might be usefull to post some of the code here.
So for this simple example I’ll just create an intellisense that gives you information about the mscorlib assembly. If you want you can adjust the code to include other assemblies as well. The first thing we need to do is get the assembly with reflection:
Assembly assembly = Assembly.GetAssembly(typeof(object));
You see I do this by getting the type of object. The reason why I do this by type and not by name is so that you can use this code for any .NET version you want, because it will resolve the core lib by the type so you’re not bound by any version. The next step is to get all the types out of this assembly like so:
private static Type[] GetTypes()
{
Assembly assembly = Assembly.GetAssembly(typeof(object));
Type[] types = assembly.GetTypes();
return types;
}
Pretty easy. Then the only thing we need to do is to filter out the types we want. Imagine the user typing in:
System.Cons
Then it’s our job to disassemble the string and compare it to the types in the assembly:
private static IEnumerable<string> GetSuggestionsForClasses(string statement)
{
// Get the last chain in the statement which is in most cases a part of the type name
var lastStatementChain = (statement.Split('.').LastOrDefault() ?? "").Trim();
var typeNamespace = GetNamespace(statement);
var types = GetTypes();
// Filter by type
var allTypes = types.Where(x => x.Namespace.Equals(typeNamespace) && x.Name.Contains(lastStatementChain))
.Select(x => x.Name);
// filter by namespace
var allNameSpaces = types.Where(x => !String.IsNullOrEmpty(x.Namespace) &&
x.Namespace.Contains(typeNamespace))
.Select(x => x.Namespace);
// Join types and namespaces
return allTypes.Union(allNameSpaces).OrderBy(x => x);
}
private static string GetNamespace(string statement)
{
var typeNamespace = "System";
var hasNameSpace = statement.Split('.').Count() > 1; // If the statement is chained by a dot
if (hasNameSpace)
{
typeNamespace = statement.Substring(0, statement.LastIndexOf('.')).Trim(); // Extract the namespace
}
return typeNamespace;
}
This way we get intellisense with type and namespaces. We can take it a step further and detect if what the user typed in was already a type and we should show its members:
if (types.Any(x => TypeEqualsStatement(statementTrimmed, x)))
{
return GetSuggestionsForType(statementTrimmed);
}
Then to see whether the statement equals a type we use the following method:
private static bool TypeEqualsStatement(string statementTrimmed, Type x)
{
// if we have an empty statement then it's impossible to have a type
if (string.IsNullOrWhiteSpace(statementTrimmed))
return false;
// Get the last chain
var lastSeperator = statementTrimmed.LastIndexOf('.');
lastSeperator = lastSeperator == -1 ? 0 : lastSeperator;
var statementedSubtrimmed = statementTrimmed.Substring(0, lastSeperator);
// Compare to the statement minus the last chain and the last chain because the last chain can be a part of the type member
return x.FullName.Equals(statementTrimmed) || (!string.IsNullOrEmpty(statementedSubtrimmed) && x.FullName.Equals(statementedSubtrimmed));
}
We always have to be careful that we compare with and without the last chain of the method. The reason for this is that the user could have already typed in a part of a member of the type. For example if he typed in: ‘System.Console.Wr’ then the Wr is a piece of the member and we must ignore this when searching for the type. The last step is then to give a summary of all the members in the type:
private static IEnumerable<string> GetSuggestionsForType(string statement)
{
var types = GetTypes();
var type = types.FirstOrDefault(x => TypeEqualsStatement(statement, x));
var lastChain = statement.Substring(statement.LastIndexOf('.')).Trim('.', ' ');
if (type == null)
return new List<string>();
// if the last chain is the type itself then we give a full list of it's members
if (type.FullName.EndsWith(lastChain))
return type.GetMembers().Select(x => x.Name)
.Distinct();
// if the last chain isn't the type itself then we filter the members
return type.GetMembers().Where(x => x.Name.Contains(lastChain))
.Select(x => x.Name)
.Distinct();
}
We can then poor this Enumerable of strings inside the listbox of a popup and show it under the text. If you're curious in how to align this popup under the desired text then look at this post.
That’s how you can build a simple intellisense!
Until next time.
woensdag 20 juli 2011
Html + jQuery vs Silverlight: part 2. 3D Navbar with flying views
In theprevious post I gave a basic comparison between jQuery and Silverlight based on simple animations. Today, I’ll be taking the animations a step further.
I’m going to attempt to make a simple semi-3D UI with some animations, first in Silverlight and then in jQuery. As I said in the previous post, I’m no jQuery expert so if there are simpler ways for doing the things I’m attempting here than just let me know. Let’s get started.
Let me start by explaining the idea for the UI. As always I’ll use the only tool I can call myself professional in… paint.
So the idea would be that Panel1 would rotate around its Y axis to provide a 3d like side panel (my paint skills proved inadequate so you’ll have imagine it). The rotation should happen when the user starts up the page so we get a neat star trek / minority report like effect. Then when one of the buttons is clicked, a view is loaded on the right side. When the view comes into screen it will slide in from bottom to top. If a view is already loaded then that view will slide away to the top.
This is how the page translates in Silverlight:
At first we’ll need to create a page with a grid that has 2 columns: one for the 3D panel and one for the View sliding in. Since this is just a demo, I’ll be loading in a Usercontrol as a view instead of a whole page.
So in our main page we have the following code:
<Grid x:Name="LayoutRoot" Background="White">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded" SourceName="stackPanel">
<ei:GoToStateAction StateName="End"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:3"/>
<VisualTransition From="Begin" GeneratedDuration="0:0:3" To="End"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Begin"/>
<VisualState x:Name="End">
<Storyboard>
<DoubleAnimation Duration="0" To="-20" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="stackPanel" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="stackPanel" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)" Storyboard.TargetName="stackPanel" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationY)" Storyboard.TargetName="stackPanel" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="stackPanel" VerticalAlignment="Stretch" Background="#FFD4D4D4">
<StackPanel.Projection>
<PlaneProjection/>
</StackPanel.Projection>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ei:GoToStateAction TargetName="View1" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View2" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View3" StateName="Out">
</ei:GoToStateAction>
</i:EventTrigger>
</i:Interaction.Triggers>
<Button Margin="0,5,0,5" Content="Button1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="View1" StateName="In">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View2" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View3" StateName="Out">
</ei:GoToStateAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Margin="0,5,0,5" Content="Button2">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="View1" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View2" StateName="In">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View3" StateName="Out">
</ei:GoToStateAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Margin="0,5,0,5" Content="Button3">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="View1" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View2" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View3" StateName="In">
</ei:GoToStateAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
<local:viewControl x:Name="View1" Grid.Column="1" d:LayoutOverrides="Width, Height" Background="#FFFFB0B0"/>
<local:viewControl x:Name="View2" Grid.Column="1" d:LayoutOverrides="Width, Height" Background="#FFE8FFAA"/>
<local:viewControl x:Name="View3" Grid.Column="1" d:LayoutOverrides="Width, Height" Background="#FF89D0FF"/>
</Grid>
</UserControl>
As you can see the 3D effect is very easy to do in Silverlight by transforming the control. The animation can be simply triggered by a GoToStateAction, so no code required. In this page there are only 2 states defined called begin and end. These states are for the 3D effect in the side bar.
Then we create a Usercontrol that will represent our Views. Below is the markup for the Usercontrol:
<Grid x:Name="LayoutRoot" Width="250" Height="250" RenderTransformOrigin="0.5,0.5" Background="{Binding Background, ElementName=userControl}" DataContext="{Binding Source={StaticResource Text}}">
<Grid.RenderTransform>
<CompositeTransform/>
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:1"/>
<VisualTransition From="Begin" GeneratedDuration="0:0:1" To="In"/>
<VisualTransition From="In" GeneratedDuration="0:0:1.0001" To="Out"/>
<VisualTransition From="Out" GeneratedDuration="0" To="Begin"/>
<VisualTransition From="In" GeneratedDuration="0" To="Begin"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Begin">
<Storyboard>
<DoubleAnimation Duration="0:0:1.5" To="-600" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="In"/>
<VisualState x:Name="Out">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True">
<LinearDoubleKeyFrame Value="600" KeyTime="0:0:1"/>
<LinearDoubleKeyFrame Value="-600" KeyTime="0:0:1.0001"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
Again very easy markup. We create three states for our animation.
- The Begin state will set the layoutroot to the bottom of the page where we wait for the animation.
- The In state will be our layout in its original position
- The Out state will be our layout root set to the top of our page
Now when we have our views with the appropriate state you can see in the markup of the page that we trigger a different state with each button. For example on Button1 we want the first view to come in and the other views to go out.
<Button Margin="0,5,0,5" Content="Button1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="View1" StateName="In">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View2" StateName="Out">
</ei:GoToStateAction>
<ei:GoToStateAction TargetName="View3" StateName="Out">
</ei:GoToStateAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
The total markup code for this example was approximately 160 lines. As you can see, it’s clear that Silverlight was made for this kind of stuff. The markup is easy to understand and even without blend you can build a very solid UI. The beauty of this all is that you don’t have to write a single line of C# (or VB.NET) to trigger the animations.
Now let’s do the same in jQuery.
At first we’ll create our html:
<div style="width: 500px; height: 400px;">
<div id="SideBar" style="background: grey; height: 450px; width: 150px;">
<button id="button1" style="width: 140px; margin: 10px 0px 10px 0px">
Button1</button>
<button id="button2" style="width: 140px; margin: 10px 0px 10px 0px">
Button2</button>
<button id="button3" style="width: 140px; margin: 10px 0px 10px 0px">
Button3</button>
</div>
<div id="View1" style="width: 250px; height: 250px; background: lightblue; position: absolute;
top: -800px; left: 200px;">
</div>
<div id="View2" style="width: 250px; height: 250px; background: lightgreen; position: absolute;
top: -800px; left: 200px;">
</div>
<div id="View3" style="width: 250px; height: 250px; background: lightpink; position: absolute;
top: -800px; left: 200px;">
</div>
</div>
So the html is no rocket science, now we need to apply the transformations. To do this I cheated a little bit and I searched for a jQuery library that can do the 3D transformation for me. The one I ended up using is Rotate3Di .
So on the load of the document we start the animation that will rotate our panel. Then when one of the buttons is clicked, we animate the div’s properly:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('#SideBar').rotate3Di(-15,3000);
});
$(":button").click(function () {
if (this.id == "button1") {
$("#View1").css("top", 800);
$("#View1").animate({ top: "20px" }, 1500);
$("#View2").animate({ top: "-=600px" }, 1500);
$("#View3").animate({ top: "-=600px" }, 1500);
}
else if (this.id == "button2") {
$("#View2").css("top", 800);
$("#View2").animate({ top: "20px" }, 1500);
$("#View1").animate({ top: "-=600px" }, 1500);
$("#View3").animate({ top: "-=600px" }, 1500);
} else if (this.id == "button3") {
$("#View3").css("top", 800);
$("#View3").animate({ top: "20px" }, 1500);
$("#View1").animate({ top: "-=600px" }, 1500);
$("#View2").animate({ top: "-=600px" }, 1500);
}
});
</script>
To my surprise the Html and jQuery solution is smaller than the Silverlight one! Only 44 lines! The code does seem awfully similar to Silverlight. This could be tribute to the fact that I first made the Silverlight application thus had the solution branded in my head, or it could be that they just do exactly the same thing besides expressing it in a different way, one in a more declarative way while the other in an imperative way.
So then why should you use Silverlight as it just brings in the overhead of installing a plugin and does not make your life easier? Well there are a couple of reasons why in this example you would take Silverlight over the jQuery solution.
First of all, the rendering kind of sucks when doing it with jQuery. Look at the two screenshots and tell me which looks better:
This is off course tribute to the fact that Silverlight has lots of fancy neat rendering tricks.
Another reason why Silverlight might be preference for this kind of stuff is because everything I did to achieve this was native to Silverlight. I did not have to search for any third party scripts, though this could also be a problem because with Silverlight I am completely dependent on the implementation of Microsoft.
The Silverlight solution is truly cross browser. I have tried it on Chrome, Firefox and Internet Explorer and all of them render the solution exactly the same. The jQuery solution isn’t. On IE it would not work and the rendering was different on Chrome and Firefox.
Yet jQuery does have the big advantage by not needing any third party add-ins to run in your browser. This might seem trivial compared to the disadvantages but it’s not. Customers located in hospitals or other facilities, where an update requires a whole regime of acceptance tests, will be left in the cold if you develop this in Silverlight.
The Html and jQuery solution also uses long proven technologies and with the forthcoming Windows 8 they aren’t likely to disappear soon. Silverlight on the other is rather new and has an uncertain future. It’s doubtful it will go away within a couple of years but its focus is shifting more and more away from the web.
That’s it for today, till next time :)
Note: files and examples will be up at the end of this week.
Abonneren op:
Posts (Atom)