Perception of innovation in Windows


Saw this infographic today:

20130129-114026.jpg

It shows clearly when public perception of innovation from Microsoft ended. Windows 2000 and its followers, although technically vastly superior, didn’t bring anything new for the users. Changes in Windows UI since Windows 98 have received a very apt nomenclature – eye candy. It could just be that Microsoft did a bad job of communicating to the public. Microsoft obviously did not fare badly, the increased technical superiority attracted enterprise use. Now, that may not be enough though, several enterprises will be force upgraded to Windows 7, they are happy enough with XP.

What my iPad needs


I love my iPad. The retina display is all I was hoping it would be. Print replica books and magazines appear really nice, and there is no need to perennially zoom in and out. I can see why Apple used the form factor it did. It makes a lot of sense.

Here’s what my iPad needs to become more useful to me.

More browsers

Safari is good. It just has a slower upgrade cycle than Chrome and Firefox. I think iPad deserves a more varied set of browsers, instead of browsers that just embed Safari. I am a big fan and user of Google services. Although most do a good job of supporting Safari, certain features are only supported in Chrome.

Bluetooth mouse

I know, iPad is touch-based and all that, but a mouse would make access to remote PCs a better experience. I don’t want to carry my PC everywhere I go. I also see the PC migrating to the cloud, eventually.

LogMeIn is one example of a remote client that does a good job of replacing a mouse with touch gestures, maybe I’ll get used to it someday. I still think a mouse has better accuracy and control for certain tasks.

Full-featured apps

I can understand why most apps adapted for the iPad suck, they are derived from the code base of their Smartphone brethren. I think it is time for the apps to better use the large screen estate and provide more features. I don’t want to switch between apps and their full-featured web counterparts, all the time. For social and communication apps where notifications are important, I can’t see myself using only the web interface either. Unless the browser apps some day integrate into the notification infrastructure of the operating system.

More flash memory

I can see the iPad replacing my laptop some day. The 64 GB flash memory limit is just not enough if and when that happens.

Phone app

I don’t have 3G or LTE on my iPad since I use it mostly at home with WiFi. I would if it had a phone app though. I don’t understand why it does not have a phone app. I don’t really use a phone that much but emergencies do happen. Who knows I may even just carry my iPad (with a headset) instead of both a phone and an iPad.

Apple needs a larger phone


…Or a smaller iPad. iPad Micro?

People are enamored with large-screen phones. Why carry a tablet and a phone when you can carry just one device that can be both? The problem is, the screen resolution on current devices is not enough, especially for print replica magazines and books.

If I were Apple, I would make a larger phone with the same pixel resolution as the retina iPad (4th Gen). If it had a PPI of 600, it would have a 4.3 inch screen. Text on it would look beautiful even without anti-aliasing. I heard print magazines use 1200 dpi for text, so it would be as good as print with some anti-aliasing still in use.

Developers would be able to scale their apps quickly, with only minor tweaks to touch widgets so they are not inconveniently small. The 4×3 aspect ratio could be a boon for readers I suppose. I wish I could hold and see such a device instead of having to imagine it…

While on the subject of screen resolution, I am so hoping Apple will come out with a retina display iPad Mini. It is a question of when, not if, I suppose.

Some tips for drawing diagrams with custom controls


Making diagrams the main UI for your application is easier than it may seem at first. The Windows Forms API provides mechanisms such as overriding the OnPaint method, and drawing primitive shapes using methods of the Graphics object, that make the task relatively easy.

Ordering of the controls

The order in which controls are added to the parent control’s Controls collection, determines the order in which they’ll appear. Thus, if you want to show one control over the other, just change its ordering in the Controls collection.

Eliminating flicker

It is possible to get flicker-free performance by setting the DoubleBuffered property of the UserControls to true. Now, if you go about moving the controls and repainting, you’ll see much less flickering.

Custom Shapes

You can leverage the GraphicsPath class to create custom shapes such as rectangles with rounded corners.

Transparent background around irregular shapes

A control may have a shape that is not a rectangle, an ellipse for instance. You want to be able to see the controls that are beyond the area of the ellipse. The default behavior is to see a rectangular background even if the region has not been painted by your code. To draw irregularly shaped controls you can set the Control.Region property.

Moving Controls

Probably the most common need is to move the controls around using the mouse. This can be done quite simply by handling the MouseMove event and some code:

    int newX = control.Left + e.X - xOffset;
    newX = newX > 0 ? newX : control.Left;
    //newX = newX > this.Width - control.Width ? control.Left : newX;
    control.Left = newX;
    int newY = control.Top + e.Y - yOffset;
    newY = newY > 0 ? newY : control.Top;
    //newY = newY > this.Height - control.Height ? control.Top : newY;
    control.Top = newY;

Uncomment the commented lines of code if you want to restrict the control to the visible area of the parent.

Reducing rate at which controls are moved

If you move your controls around, especially beyond the visible area of the parent control, you’ll notice that the controls just zip around at high speed. To make things more usable by us humans, we can limit that rate. This is the same as restricting a game to a certain frame rate. Besides helping the user, restricting the rate also reduces CPU usage by preventing it from doing unnecessary unappreciated work.

This can be achieved by code such as:

    int tickCount = Environment.TickCount;
    if (tickCount - this.tickCount > 40 || tickCount < this.tickCount)
    {
        this.tickCount = tickCount;
    }
    else
    {
        // limit mouse movement
        return;
    }

Here, we restrict the rate of movement to 25 per second, by ensuring that the event handler for mouse move returns unless 40 milliseconds have elapsed since the last time it did useful work. Environment.TickCount property counts the number of milliseconds elapsed since the system was started. We’ve also considered the fact that Environment.TickCount may overflow at some point in time.

Drawing primitive shapes

Probably the hardest thing I had to do is draw a straight line connector between two shapes. It is hard to do because I wanted to place a label on the connector and position it in code. I reproduce the code below as a demonstration of drawing primitive shapes and text.

void drawConnector(Graphics graphics, UserControl control1, UserControl control2, string text)
{
    int x1 = control1.Left + control1.Width / 2;
    int y1 = control1.Top + control1.Height / 2;
    int x2 = control2.Left + control2.Width / 2;
    int y2 = control2.Top + control2.Height / 2;
    graphics.DrawLine(this.linePen, x1, y1, x2, y2);

    if (text == null) return;

    SizeF size = graphics.MeasureString(text, this.font);

    int x = x1 < x2 ? 
        x1 + (x2 - x1) / 2 - (int)size.Width / 2
        : x2 + (x1 - x2) / 2 - (int)size.Width / 2;

    if (Math.Abs(x1 - x2) < size.Width)
    {
        y1 = y1 < y2 ? y1 + control1.Height / 2 : y1 - control1.Height / 2;
        y2 = y2 < y1 ? y2 + control2.Height / 2 : y2 - control2.Height / 2;
    }

    int y = y1 < y2 ? 
        y1 + (y2 - y1) / 2 - (int)size.Height / 2
        : y2 + (y1 - y2) / 2 - (int)size.Height / 2;

    y = Math.Abs(y1 - y2) < size.Height ? y - (int)size.Height / 2 : y;

    graphics.FillRectangle(Brushes.White, 
        new Rectangle(x, y, 
            (int)size.Width, 
            (int)size.Height - (int)Math.Ceiling(this.linePen.Width)));

    graphics.DrawString(text, this.font, Brushes.Black, x, y);
}

Open issues

I haven’t figured out how to draw primitive shapes in the OnPaint method of the parent control and have them appear above the child controls. I have seen some workarounds at StackOverflow and elsewhere but nothing elegant. Another thing that I have to figure out is drawing out of the bounds of the child control’s region. By default, if the child control wants to show a boundary line around itself it has to paint it within its bounds or else it will be clipped.

Where to buy tech e-books


I have adopted e-books in a big way. This is a quick post to register which publishers are selling tech e-books, and where. Most e-books they sell are more expensive than the Kindle versions sold at amazon.com, but are DRM-free and in several different formats such as EPUB, PDF, and MOBI. Some give lifetime e-book updates, will archive your e-books at services such as Dropbox, and give much cheaper e-book upgrades for print books.

  • Apress – Sells its own e-books and those from Springer.
  • InformIT – Sells its own e-books and those from Addison-Wesley Professional, Cisco Press, FT Press, IBM Press, Pearson IT Certification, Pearson Prentice Hall, Prentice Hall Professional, Que, Sams, and VMware Press.
  • O’Reilly – Sells its own e-books and those from Academic Press, Elsevier, Microsoft Press, Morgan Kaufmann, Sybex, Wiley, Wrox, and others. They also provide the Safari Books Online subscription service.
  • Packt Publishing – Popular for publishing books for open source software.
  • Wiley – Text e-Books are in PDF and EPUB formats and use the Adobe DRM. I bought my first e-book there but wasn’t able to download it and was shown a “Territory Not Authorized” message instead. At times like these I wonder who exactly is served by DRM. Definitely not the customers. The problem was eventually resolved and I was able to download the book in EPUB format.
  • Wrox – Professional e-books in PDF, EPUB and Kinlde (PRC) format.

I’ll keep this post updated as I discover more information. I have intentionally left some sources out because they have a confusing online presence and are not known for selling e-books, like McGraw-Hill Professional. Not surprisingly, most of them are college text book publishers. Most book publishers for professionals have adopted e-books in a big way, and mostly offer e-books without DRM.

xcopy


xcopy is a powerful command to repeatedly copy a directory and its sub-directories (including files) to a new destination. It can be particularly useful to developers in build scripts, or post-build event of a Visual Studio project. Here’s how I like to use it from the command line:

xcopy /Y /D /E /I /EXCLUDE:somefolder\exclude somefolder targetdir\somefolder

This will copy somefolder and all its files to targetdir/ The /Y option will suppress prompting the user for confirmation before replacing a file. The option /E tells xcopy to also copy empty folders. If you don’t want to copy empty folders, use the option /S instead. The /D option tells xcopy to only copy source files that have a more recent date and time than those at the target location. The /I option tells xcopy to create destination folder if it does not exist.

The /EXCLUDE option will leave out files and directories listed (one per line) in the file called exclude. This can be useful if you are using some kind of version control system. For example, if you have a line with the text .copyarea.db, a file used by ClearCase Remote Client, those files in any folder will not be copied to the target location.

In the post-build event of a Visual Studio project xcopy can be used thus:

xcopy /D /E /I /EXCLUDE:$(ProjectDir)..\somefolder\exclude $(ProjectDir)..\somefolder $(TargetDir)somefolder

The $(ProjectDir) macro expands to the full (absolute) path where the project is located. The $(TargetDir) macro expands to the absolute path where the build output is written. I suggest avoiding absolute paths, instead use paths relative to the project location, as shown above.

Prepare HTML document for printing


Print style sheets should work with most modern browsers, unless they don’t. I’ve had problems with IE 7 and 8 in particular. The following code snippet demonstrates how I massage my document before writing it out to an empty document or iframe.

    // jqueryObj is a set of elements returned by a selector e.g. $('*')

    // remove undesired elements
    jqueryObj.find('script').remove().end();
    jqueryObj.find('img').remove().end();
    jqueryObj.find('button').remove().end();

    // remove event handlers
    jqueryObj.find('[onclick]').removeAttr('onclick').end();
    jqueryObj.find('[onkeypress]').removeAttr('onkeypress').end();
    jqueryObj.find('[onkeyup]').removeAttr('onkeyup').end();
    jqueryObj.find('[onblur]').removeAttr('onblur').end();
    jqueryObj.find('[onfocus]').removeAttr('onfocus').end();
    jqueryObj.find('[onchange]').removeAttr('onchange').end();

    // avoid scrollbars
    jqueryObj.find('div').css('width', '100%').end();
    jqueryObj.find('div').css('height', 'auto').end();
    jqueryObj.find('div').css('overflow', 'hidden').end();
    jqueryObj.find('ul').css('height', 'auto').end();
    jqueryObj.find('ul').css('overflow', 'hidden').end();

    // disable form input elements
    jqueryObj.find('input').attr('readonly', 'readonly').end();
    jqueryObj.find('input[type="radio"]').attr('disabled', 'disabled').end();
    jqueryObj.find('select').attr('disabled', 'disabled').end();

Additionally, you can remove undesired CSS classes thus:

    jqueryObj.find('.class1').removeClass('class1').end();

There may be a better alternative to render form input elements unchangeable. The manner implemented here causes them to appear grayed out. Tweaking their style with CSS so that they don’t appear grayed out may help. Another option is to use an absolutely positioned transparent div on top of everything else:

<div style="position:absolute;top:0;left:0;height:100%;width:100%;z-index:999;background-color:white;opacity:0;filter:alpha(opacity=0);"></div>