UltraWebTab: Switch to Tab on Validation Error

June 24, 2009

The Problem

I have an ASP.Net form that contains a set of tabs hosted inside an Infragistics UltraWebTab control. Each tab contains a number of fields that have validation. Sometimes, when the user submits the form, a validation error occurs. When this happens, I want the user to be able to correct the error with a minimum of fuss – I want the tab containing the error to be automatically selected, and the control with the error to be given the focus.

The Solution

The following code causes the first tab that contains an error to be selected when the form submits:

// These scripts are responsible for handling validation error messages in the tabs.
// If there are any errors on the page, they switch to the tab containing the first
// error and ensure that the control with the error is focused.

 function preValidate() {
  // For each of the validators on the page...
  var i;
  for (i = 0; i < Page_Validators.length; i++) {
   // Perform the validation.

   // If invalid data is found...
   if (!Page_Validators&#91;i&#93;.isvalid) {

    // Get the control that failed validation.
    var badControl = document.getElementById(Page_Validators&#91;i&#93;.controltovalidate);

    // Focus it.

    // Stop processing validation.

  } // Next validator.

  // The page is valid.


 function focusInvalid(badControl) {

  // Get the index of the tab that contains this control.
  var tabIndexToFocus = getContainingTabIndex(badControl);
  if (tabIndexToFocus > -1) {
   // Switch to the tab that contains the validation error.
   var ultraTab = igtab_getTabById('<%=UltraWebTab1.ClientID %>');

   // Focus the control and exit.

 function getContainingTabIndex(targetControl) {

  var ultraTab = igtab_getTabById('<%=UltraWebTab1.ClientID %>');

  // Get a reference to the tabs.
  var tabs = ultraTab.Tabs;

  // Start with the control that failed to validate.
  var testControl = targetControl;

  // While we have not got to the top of the control heirarchy...
  while (targetControl != null) {
   // Walk up the DOM to seek out the tab panel that contains the target control.
   testControl = testControl.parentNode;

   // For each of the tab panels...
   var tabIndex;
   for (tabIndex = 0; tabIndex < tabs.length; tabIndex++) {
    if (tabs&#91;tabIndex&#93;.elemDiv == testControl) {
     return tabIndex;
   } // Next index.

  } // Wend.

  // The control is not contained in a tab panel.
  return -1;

To run the script, attatch it to the OnClientClick event of the button that submits the form:

&#91;sourcecode language='html'&#93;<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnEdit_Click" OnClientClick="preValidate();" />

Note that validation of each control will happen twice if the form is valid; once for the code above and then once because that’s how ASP.Net works. This doesn’t normally matter with the standard ASP.Net controls, but it might be an issue with badly-written custom validation controls. You have been warned!

MIDP 1.0 fillTriangle Method

June 1, 2009

One of the (many) limitations of MIDP 1.0 is that it lacks the fillTriangle that is present in MIDP 2.0. Below is a replacement method that works on MIDP 1.0 devices. It is based on notes published by Michal Wronski.

Michal’s algorithm depends on floating-point math – also unavailable in MIDP 1.0. With a little refactoring I was able to create an integer-only approximation. Sadly, rounding errors mean that my routine isn’t pixel perfect. An alternative that would give more accurate results would be to use some kind of fixed-point library. Despite its shortcomings, however, my method is good enough for many practical purposes (including my own).

protected void drawHorizontalLine(int x1, int x2, int y)
graphics.drawLine(x1, y, x2, y);

protected void fillTriangle(int ax, int ay, int bx, int by, int cx, int cy)
// http://www.geocities.com/wronski12/3d_tutor/tri_fillers.html

// Sort the points so that ay <= by <= cy int temp; if (ay > by)
temp = ax;
ax = bx;
bx = temp;
temp = ay;
ay = by;
by = temp;
if (by > cy)
temp = bx;
bx = cx;
cx = temp;
temp = by;
by = cy;
cy = temp;
if (ay > by)
temp = ax;
ax = bx;
bx = temp;
temp = ay;
ay = by;
by = temp;

// Calc the deltas for each edge.
int ab_num;
int ab_den;
if (by – ay > 0)
ab_num = (bx – ax);
ab_den = (by – ay);
ab_num = (bx – ax);
ab_den = 1;

int ac_num;
int ac_den;
if (cy – ay > 0)
ac_num = (cx – ax);
ac_den = (cy – ay);
ac_num = 0;
ac_den = 1;

int bc_num;
int bc_den;
if (cy – by > 0)
bc_num = (cx – bx);
bc_den = (cy – by);
bc_num = 0;
bc_den = 1;

// The start and end of each line.
int sx;
int ex;

// The heights of the two components of the triangle.
int h1 = by – ay;
int h2 = cy – by;

// If a is to the left of b…
if (ax < bx) { // For each row of the top component... for (int y = 0; y < h1; y++) { sx = ax + ac_num * y / ac_den; ex = ax + ab_num * y / ab_den; drawHorizontalLine(sx, ex, ay + y); } // For each row of the bottom component... for (int y = 0; y < h2; y++) { int y2 = h1 + y; sx = ax + ac_num * y2 / ac_den; ex = bx + bc_num * y / bc_den; drawHorizontalLine(sx, ex, by + y); } } else { // For each row of the bottom component... for (int y = 0; y < h1; y++) { sx = ax + ab_num * y / ab_den; ex = ax + ac_num * y / ac_den; drawHorizontalLine(sx, ex, ay + y); } // For each row of the bottom component... for (int y = 0; y < h2; y++) { int y2 = h1 + y; sx = bx + bc_num * y / bc_den; ex = ax + ac_num * y2 / ac_den; drawHorizontalLine(sx, ex, by + y); } } } [/sourcecode] I release this code into the public domain. You can use it as you please.

Source Code Formatting in WordPress

June 1, 2009

Finally, I have found the document that describes how this can be done:


Great Programming Books: 2008

December 10, 2008

Last year, I made a list of Great Programming books. Here is an update to that list.

I have read and highly recommend the following:

These are often recommended by people who have read the above:

  • Alan Cooper, “The Inmates Are Running the Asylum: Why High Tech Products Drive Us Crazy and How to Restore the Sanity
  • Tom DeMarco and Timothy Lister , “Peopleware – Productive Projects and Teams
  • Martin Fowler, “Patterns of Enterprise Architecture
  • Eric Freeman, Elisabeth Freeman, Kathy Sierra, Bert Bates, “Head First Design Patterns
  • Erich Gamma et al, “Design Patterns: Elements of Reusable Object-Oriented Software
  • Andrew Hunt and David Thomas , “The Pragmatic Programmer: From Journeyman to Master
  • Bertrand  Meyer, “Object-oriented Software Construction

Other people’s ideas about great programming books:

More .Net Cheat Sheets

December 1, 2008

I have linked a few before.

There are more here:

Quote: Programmers are Romantics

December 1, 2008

Programmers are romantics. We’re lovers not fighters.

Why, developers are widely regarded as being the sexiest creatures on the planet. Our beauty causes people in other professions to go blind. We are love. We are truth. We are sex at a keyboard.

— Peter O’Hanlon, Code Project.

Mini Book Review: Graphics Programming in Windows (Charles Petzold)

November 14, 2008

Graphics Programming in Windows

My personal library is overcrowded, so over the years I have found it necessary to dispose of many books on outmoded technology. This book by Charles Petzold is different. Indeed, its unparalleled coverage of graphics programming techniques make it worth every inch of the space it takes up on my shelf.

Indeed, this book is a timeless classic. Although this it was written some time in the 1990s, its contents apply equally well to modern versions of Windows. Of course, it lacks details of the innovations that have occurred since it was written, but the programming techniques that it espouses will be as useful now as ever they were. Indeed, it is hard to find fault with a single example given in this volume.

Some people may find the book a little brief in places. Indeed, it does lack the depth of cover found in Petzold’s other books. Nevertheless, this book is without comparison in its subject area. If anyone is looking for a book on Windows Graphics, you’d be hard pressed to find one that is as informative as this one.

Sadly, Amazon lists this book as out of print. But, if you can obtain a copy of this book, I urge you to buy it. You won’t be sorry.

In short, highly recommended!