Archive for March, 2010
On Labels and Triggers
Designing form for web pages is not an easy task. No one likes to fill out a form, and most people are uncomfortable when there are more than just a few of controls. Layout of elements that focuses the user’s view on the most important elements, and leads her through the process until completion, makes a huge difference, but there’s more. A web form is not only perceived by the eye, but also by the hand – through the medium of a keyboard or a mouse.
For some people, the tab order in forms in paramount. This is a known and accepted fact in the realm of business applications, and rightfully so. On many forms on the Internet however, the sentence “tab order is important” seems to raise the same reaction as “the moon is made of green cheese”. The big benefit of using the tab key is that you never have to leave the keyboard. A test script for any form, anywhere, should include a test like that:
- When I open the form, the first control is focused: I can start typing without first manually selecting a control.
- When I hit “tab”, the focus moves to the next control in a logical order that is intuitive from the layout of the form.
- When I’m done with filling in data, the focus is on the button or link that executes an action to commit the entered data somehow so that I just have to hit “Enter” to activate it.
Try that on your favorite web site/application.
Another behavior that users expect is that clicking the label next to a control sets the focus. With smaller controls, this behavior increases the area that can be used so that less precision on the user’s side is required. And then there’s people like me who literally can’t read a web site without the finger on the trackpad. I tend to support the point I’m looking at with the cursor, and highlight text that I find interesting (sitting next to me and trying to read the same page isn’t such a good idea). So when I want to select a control on a form, the intuitive thing to do is to click the label – the cursor is there already anyway.
Works on WinForms. Works in HTML (when the tag has been used). In Silverlight? Nope. There is a control called “Label” in System.Windows.Controls.Data.Input.dll that is specifically built for the purpose of acting as a label for controls, but does it implement the selection behavior? Guess.
Luckily, it is extremely easy to build the necessary behavior into a label control of your own.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace GreenIcicle.Controls
{
public class ControlLabel : ContentControl
{
protected override void OnMouseLeftButtonUp( MouseButtonEventArgs args )
{
base.OnMouseLeftButtonUp( args );
if( Target != null )
{
Target.Focus();
}
// Toggle checkboxes: If a target derives from ToggleButton,
// toggle its value when then label is clicked AND the control
// already has the focus. So for unfocused controls, the
// first click focuses the control and the second toggles it.
ToggleButton toggleableTarget = Target as ToggleButton;
if( toggleableTarget != null && toggleableTarget.IsFocused )
{
// If the toggleable control is indetermined,
// treat it as unchecked
bool isChecked = toggleableTarget.IsChecked ?? false;
// Toggle the IsChecked state
toggleableTarget.IsChecked = !isChecked;
}
}
public virtual Control Target
{
get { return (Control)GetValue( TargetProperty ); }
set { SetValue( TargetProperty, value ); }
}
public static DependencyProperty TargetProperty = DependencyProperty.Register(
"Target",
typeof( Control ),
typeof( ControlLabel ),
null );
}
}
Usage:
<gi:ControlLabel
Target="{Binding ElementName=Text1}"
Content="Some text please">
<TextBox
x:Name="Text1"/>
A solution I would have liked a lot more than creating a special control would have been the usage of a trigger. A trigger is defined within the XAML markup in order to add behavior to this element; and because the Silverlight styles are such a strong concept, adding behavior to _exisiting_ controls via triggers looks like a great idea. Except that it does not work in a very interesting way. So this was what I tried: Imported System.Windows.Controls.Data.Input as “dctrl”, and
<dctrl:Label Content="Some text please" > <dctrl:Label.Triggers> <EventTrigger RoutedEvent="UIElement.MouseLeftButtonUp" > <BeginStoryboard> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsFocused" Storyboard.TargetName="Text1" > <DiscreteObjectKeyFrame KeyTime="0" Value="True"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </dctrl:Label.Triggers> </dctrl:Label> <TextBox x:Name="Text1"/>
So what I wanted to do is to let the trigger fire on the MouseLeftButtonUp event (you need to declare routed events on the class that declare them; that’s why it’s UIElement.MouseLeftButtonUp), and when that happens, run a storyboard that sets the IsFocused property on the text box to True.
What I got is a runtime XamlParseException that says “Attribute UIElement.MouseLeftButtonUp value is out of range”.
The reason is that EventTriggers in Silverlight only support the Loaded event (as stated here):
In Silverlight, the only event that you can use for an EventTrigger is the Loaded event. For other events, you should declare a storyboard in the Resources property, provide a Name value for the storyboard, and write an event handler that calls the Begin method on the named storyboard.
Now if I need to write an event hander, I can as well resort to the control as shown above. What I wanted to get from the trigger is declarative addition of behavior to an existing control. It’s probably my fault that I haven’t really looked into Triggers (and Behaviors are still to be looked at more closely as well…), but AFAICS, there’s not much value to them right now.
Chocolate-covered unit tests
I just went through last week’s unread feed (a sleeping problem? me?) and found this on the Daily WTF. The unit test code you see there is so absurdly wrong it makes you smile, but then, there’s a serious problem behind that.
The author has been assigned to implement a development process that utilizes unit testing with a team whose members don’t buy into the idea. So management escalates the problem and enforces a policy that uses the code coverage metric to measure the quality of unit tests. Of course the team members still don’t buy into the whole idea of automated testing, and game the metric to the extreme.
And there’s the problem: if you want to have automated tests that really improve quality, and not just for the sake of a process requirement, you need to find a way to get developers to love them. If they don’t, they’ll find a way to weasel around any metric that you put up. All you can do then is forcefully review the tests, and live with the extra work and bad spirit that they create.
It is very easy to develop a love for unit testing when you’re the one responsible for maintenance problems. If it’s your own code that you’re living off. Or, when you’ll be held responsible for what others produce. On the other hand, if you’re mostly responsible for delivering features set in limited time, and then these result melt into some larger product, the responsibility for maintenance gets blurry.
Anyone: how do you put chocolate around a unit test?
Yet another syntax highlighter for ScrewTurn Wiki
ScrewTurn Wiki is an excellent free wiki engine. It’s open source, runs on top of ASP.NET, supports ActiveDirectory authentication, and is super-easy to set up. Because of these qualities, I use it as the default choice for product or project related internal wikis (and yes, you can of course run it on the Internet).
What ScrewTurn does not supply out of the box is syntax highlighting for source code. What it does have however is a well-documented and simple enough plugin model that allows you to roll your own. There already is a an implementation by Tim Bellette that is contained in a single DLL and looks very OK, and another one that uses the GeShi PHP application, which is good because GeShi knows every language in the world, but requires you to set up a PHP application in addition to ScrewTurn, which might be a problem or not.
Why I choose to come up with my own syntax highlighter plugin is that a) I sometimes like building stuff and need an excuse for that and b) I really like the source code formatter that WordPress uses. As you can behold it here:
// See how nice this looks? It's got line numbers, // alternating background, and these super-useful buttons // to copy the whole code into the clipboard and print it // that appear when you hover over the code.
The amazing thing about this formatter is that it is completely implemented as client-side JavaScript and CSS. Alex Gorbatchev has developed this little feat, and published it as open source. What you need to do to get code formatting onto an HTML page is to decorate a “pre” tag with a CSS class, and add links to the script files.
Letting ScrewTurn Wiki so this is quite easy. All you need to do is to write a formatter plugin. In addition to some minor infrastructure wire-up, this type of plugin lets you modify the content of a wiki article, and its title. The API for writing ScrewTurn Wiki is extremely enjoyable and well documented, deploying is a matter of seconds – you can just drop your DLL into the public/plugins directory of the web application, or even use its administrative user interface to upload new plugins into the app when you don’t have access to the server.
Usage
The markup for code in ScrewTurn Wiki is:
Text before the code @@ // Your source code goes here @@ Text after the code
In order to support wikis that already contain code following that syntax (and especially for one large project with 500+ pages…) this syntax is supported. However, it does not indicate which language the code is in, so that the formatter defaults to plain text; it still provides the line numbers and fancy background.
To indicate the language, add the name of the programming language as the first word of the code block. The name of the language can be any of the syntaxes supported by the SyntaxHighlighter. A single page in the wiki can contain code blocks in several programming languages.
@@ csharp // Comment public string Greeting = "huhu"; @@ Text between code blocks @@ xml <!-- Comment --> <node&gt;content</node&gt; @@
Configuration
In the admin UI of ScrewTurn Wiki, you can provide a configuration string for plugins. This one supports three configuration options:
- ScriptUrl The syntax highlighter needs to download some CSS, JavaScript, and Flash files. By default, these files are downloaded from my Dropbox (which makes quite a good poor man’s CDN). If you like to download them from somewhere else, specify the base URL in the ScriptUrl option. The best-performing way to deliver the files will be to download them onto the wiki’s web server and reference them with a relative URL.
- Theme The syntax highlighter offers some color-scheme themes. Pick one with this option; or omit it to use the default one.
- DefaultLang If no language is specified on a code block, the default language is used. Without specifying this option, no specific language is used and the code appears as plain text; specify the DefaultLang option to use another language as default.
In this example the script files are loaded from a directory on the wiki server with the machine-absolute URL “/syntaxHighlighter/”, the white-on-black Emacs color theme is used, and the default language is C#.ScriptUrl=/syntaxHighlighter/; Theme=Emacs; DefaultLang=csharp
- CustomLang
The syntax highlighter allows adding new javascript “brush” files in orde to support additional languages that are not included in the standard script library. *If you have not written or imported custom brush definitions, or if you don’t know what is meant by that, you do not need to set this option.*By default, the ScrewTurn plugin does not know about these custom languages. To use additional brush definitions, add a custom language to the configuration string, and add the name of the javascript file that implements it.
In this example, an additional language called “magic” is added. It uses a brush file named “shBrushMagic.js”.
CustomLang:magic=shBrushMagic.js
Note that the custom brush file has to reside in the same directory as the standard brush definition files.
You can specify multiple custom languages, and you can assign different synonyms for the same brush:
CustomLang:magic=shBrushMagic.js; CustomLang:mushroom=shBrushMagic.js; CustomLang:slippers=shBrushSlippers.js
Revisions
- 1.0 Initial Release. Uses SyntaxHighlighter 2.1
- 1.1 Uses SyntaxHightlighter 3.0
Download
DOWNLOAD SINGLE DLL
Installation: Download. Log onto ScrewTurn Wiki as an admin. Go to Administration -> Providers. Under “Providers DLLs Management”, upload the DLL: done.
SOURCE CODE
C#, Visual Studio 2010 Project – Hosted on Google Code
Licensed under LGPLv3 .
Known Issues
If you’ve got a problem installing the plug-in, or it does not work as expected, please use the Google Code issue tracking system. You’ll need to log on using a Google account.
Code blocks in tables
When you try to put a code block into a table, you’ll find out that this block won’t be formatted correctly. This is not a genuine problem of this plug-in, but caused by a general limitation in ScrewTurn wiki that does not allow any formatting in table cells. The FormatterPlus plug-in by Denis Stankovski fixes this. Together with this plug-in, code blocks in tables work fine.