Miłosz Orzeł

.net, js, html, arduino, java... no rants or clickbaits.

Coordinate system in HTML5 Canvas, drawing with y-axis value increasing upwards

Coordinate system in HTML5 Canvas is set up in such a way that its origin (0,0) is in the upper-left corner. This solution is nothing new in the world of screen graphics (e.g. the same goes for Windows Forms and SVG). CRT monitors, which were standard in the past, displayed picture lines from top to bottom and image within a line was created from left to right. So locating origin (0,0) in the upper-left corner was intuitive and it made creating hardware and software for handling graphics easier.

Unfortunately sometimes default coordinate system in canvas is a bit impractical. Let’s assume that you want to create projectile motion animation. It seems natural that for ascending projectile, the value of y coordinate should increase. But it will result in a weird effect of inverted trajectory:

Default coordinate system (y value increases downwards)

You can get rid of this problem by modifying y value that is passed to drawing function:

context.fillRect(x, offsetY - y, size, size);

For y = 0, projectile will be placed in a location determined by offsetY (to make y = 0 be the very bottom of the canvas, set offsetY equal to height of the canvas). The bigger the value of y the higher a projectile will be drawn. The problem is that you can have hundreds of places in your code that use y coordinate. If you forget to use offsetY just once the whole image may get destroyed. 

Luckily canvas lets you make changes to coordinate system by means of transformations. Two transformation methods will be useful for us: translate(x ,y) and scale(x, y). The former allows us to move origin to an arbitrary place, the latter is for changing size of drawn objects, but it may also be used to invert coordinates.

Single execution of the following code will move origin of coordinate system to point (0, offsetY) and establish y-axis values as increasing towards the top of the screen:

context.translate(0, offsetY);
context.scale(1, -1);

Translation and scaling of coordinate system. Click to enlarge...

But there’s a catch: the result of providing -1 as scale’s method second argument is that the whole image is created for inverted y coordinate. This applies to text too (calling fillText will render letters upside-down). Therefore before writing any text, you have to restore default y-axis configuration. Because manual restoring of canvas state is awkward, methods save() and restore() exist. These methods are for pushing canvas state on the stack and popping canvas state from the stack, respectively. It is recommended to use save method before doing transformations. Canvas state includes not only transformations but also values such as fill style or line width...

context.save();
 
context.fillStyle = 'red';
context.scale(2, 2);
context.fillRect(0, 0, 10, 10);
 
context.restore();
 
context.fillRect(0, 0, 10, 10);

Above code draws 2 squares: 

First square is red and is drawn with 2x scale. Second square is drawn with default canvas settings (color black and 1x scale). This occurs because right before any changes to scale and color, canvas state was save on the stack, later on it was restored before second square drawing.

TortoiseSVN pre-commit hook in C# - save yourself some troubles!

Probably everyone who creates or debugs a program happens to make temporary changes to the code that make current task easier but should never get into the repository. And probably everyone has accidentally put such code into next revision. If you are lucky enough, mistake will be revealed quickly and the only result will be a bit of shame, if not...

If only there was a way to mark “uncommitable” code...

You can do it and it’s pretty simple!

TortoiseSVN lets you set so-called pre-commit hook. It’s a program (or script) that is run when user clicks “OK” button in “SVN Commit” window. Hook can for example check content of modified files and block commit when deemed appropriate. Tortoise hooks differ from Subversion hooks in that they are executed locally and not on the server that hosts the repository. You therefore don’t have to worry whether your hook will be accepted by the admin or if it works on the server (e.g. server may not have .NET installed), you also don’t affect the experience of other users of the repository. Client-side hooks are quicker too.

Detailed description of hooks can be found in „4.30.8. Client Side Hook Scripts” chapter of Tortoises help file.

Tortoise supports 7 kinds of hooks: start-commit, pre-commit, post-commit, start-update, pre-update, post-update and pre-connect. We are concerned with pre-commit action. The essence of the hook is to check whether one of added or modified files contains temporary code marker. Our marker may be a “NOT_FOR_REPO” text put into a comment placed above temporary code.

This is whole hook’s code – simple console application, that may save your ass :)

using System;
using System.IO;
using System.Text.RegularExpressions;

namespace NotForRepoPreCommitHook
{
    class Program
    {
        const string NotForRepoMarker = "NOT_FOR_REPO";

        static void Main(string[] args)
        {              
            string[] affectedPaths = File.ReadAllLines(args[0]);

            Regex fileExtensionPattern = new Regex(@"^.*\.(cs|js|xml|config)$", RegexOptions.IgnoreCase);

            foreach (string path in affectedPaths)
            {
                if (fileExtensionPattern.IsMatch(path) && File.Exists(path))
                {
                    if (ContainsNotForRepoMarker(path))
                    {
                        string errorMessage = string.Format("{0} marker found in {1}", NotForRepoMarker, path);
                        Console.Error.WriteLine(errorMessage);    
                        Environment.Exit(1);  
                    }
                }
            }             
        }

        static bool ContainsNotForRepoMarker(string path)
        {
            StreamReader reader = File.OpenText(path);

            try
            {
                string line = reader.ReadLine();

                while (line != null)
                {
                    if (line.Contains(NotForRepoMarker))
                    {
                        return true;
                    }

                    line = reader.ReadLine();
                }
            }
            finally
            {
                reader.Close();
            }  

            return false;
        }
    }
}

TSVN calls pre-commit hook with four parameters. We are interested only in the first one. It contains a path to *.tmp file. In this file there is a list of files affected by current commit. Each line is one path. After loading the list, files are filtered by extension (useful if you don’t want to process files of all types). Checking if file exists is also important – the list from *.tmp file contains paths for deleted files too! Detection of the marker represented by NotForRepoMarker constant is realized by ContainsNotForRepoMarker method. Despite its simplicity it provides good performance. On mine (middle range) laptop, 100 MB file takes less than a second to process. If marker is found, program exits with error code (value different than 0). Before quitting, information about which file contains the marker is sent to standard error output (via Console.Error). This message will get displayed in Tortoise window.

The code is simple, isn’t it? In addition, hook installation is also trivial!

To attach hook, choose “Settings” item from Tortoise’s context menu. Then select “Hook scripts” element and click “Add…” button. Such window will appear:

TSVN hooks configuration window

Set „Hook Type” to „Pre-Commit Hook”. Fill “Working Copy Path” field with a path to the directory that contains local copy of the repo (different folders can have different hooks). In “Command Line To Execute” field, set path to the application that implements the hook. Check “Wait for the script to finish” and “Hide the script while running” options (the latter will prevent console window from showing). Press “OK” button and voila, hook is installed!

Now mark some code with “NOT_FOR_REPO” comment and try to execute commit. You should see something like that:

Operation blocked by pre-commit hook

Notice the „Retry without hooks” button – it allows commit to be completed by ignoring hooks.

We now have a hook that prevents from temporary code submission. One may also want to create a hook that enforces log message to be filled, blocks *.log files commits etc. Your private hooks – you decide! And if some of the hooks will be usefull for the whole team, you can always remake them as Subversion hooks.

Tested on TortoiseSVN 1.7.8/Subversion 1.7.6.

Update 24.03.2014: Added emphasis to checking "Wait for the script to finish" option - without it hook will not block commits!

Update 17.09.2013: (additional info): You may set hook on a parent folder which contains multiple repositories checkouts. If you are willing to sacrifice a bit of performance for added protection you may resign from filtering files before checking for NotForRepoMarker marker.  

How to close pop-ups upon main window closure or logout?

Imagine you have to provide support for some really old web application. The app has one main window and pop-up windows that show some sensitive information (for example payroll list). Client wants to ensure that all pop-ups are closed when user leaves main window or clicks “logout” button in this window...

So... how to close all the windows opened with window.open?

On the web this question comes up very often. Unfortunately, most common answer is really naive. Proposed solution is based on keeping references to opened pop-ups and subsequent invocation of close method: 

var popups = []; 
 
function openPopup() {
    var wnd = window.open('Home/Popup', 'popup' + popups.length, 'height=300,width=300');
     
    popups.push(wnd);
}
 
function closePopups() {
    for (var i = 0; i < popups.length; i++) {
        popups[i].close();
    }
 
    popups = [];
}

In practice this doesn’t work because the array of references is cleared at full page reload (for example after clicking on a link or upon postback)...

Other suggested solution is to give the pop-up a unique name (using the second parameter of the open method) and later acquisition of a reference to the window:

var wnd = window.open('', 'popup0');
wnd.close();

This is based on the fact, that window.open method works in two modes:

  1. If a window with a given name doesn’t exist, it is created.
  2. If a window with a given name does exist, it will not be recreated, instead a reference to that window will be returned (if non empty URL is passed to the open method pop-up will be reloaded).

The problem lies at point no. 1. If pop-up window with given name wasn’t previously opened, the call to open and close methods will cause the pop-up to be briefly visible. It sucks…

But maybe a reference to pop-up can be retained between page reloads?

If there is no need to support older browsers (unlikely for the old application) we can try to put reference to the pop-up window into localStorage. However, this will not work:

var popup = window.open('http://morzel.net', 'test');
localStorage.setItem('key', JSON.stringify(popup)); 
 
TypeError: Converting circular structure to JSON

Old tricks for keeping page state between reloads that are based on cookies or window.name will not work too.

 

So… what to do?

Even if you can’t afford to have a major change such as introducing frames, don’t give up :)

Pop-up windows have opener property that points to parent window (that is the window in which the call to window.open was placed). Pop-ups can therefore periodically check whether the main window still remains open. Additionally, pop-ups can also access variables from parent window. This can be used to enforce pop-ups closure when main window is closed or when user clicks on “logout” button in parent window. When user is logged-in (and only then!), a marker variable (i.e. loggedIn) should be set in main window.

Here is the JS code that should be placed on a page displayed in a pup-up:

window.setInterval(function () {
    try {
        if (!window.opener || window.opener.closed === true || window.opener.loggedIn !== true) {
            window.close();
        }
    } catch (ex) {
        window.close(); // FF may throw security exception when you try to access loggedIn (for external site)
    }
}, 1000);

Checking variable from the opener window has another advantage. If user moves away from our application in main window (for example by clicking back button or a link to an external website), then the pop-up window will detect the lack of monitored variable in window.opener and close automatically.

Well, it's not the kind of code you enjoy to write but it achieves the desired result despite the painful gaps in the browsers API. If only they provide us with window.exists('name') method...

Ref modifier for reference types and a bit of SOS

Take a look at the following code and think what value will be displayed on the console (note that string is a reference type)?

using System;
               
class Program
{
    static void Test(string y)
    {
        y = "bbb";
    }

    static void Main()
    {
        string x = "aaa";
        Test(x);
        Console.WriteLine(x);
    }
}

The correct answer (aaa) is not all that obvious. You will see the words aaa, because without a ref modifier, a program written in C# provides a copy of the parameter value (for value types) or a copy of a reference (for reference types).

When parameter y in method Test receives a new text value, CLR does not modify the array of chars. Instead, a new string is created and a reference to it is assigned to variable y (more info here). Variable y contained in method Test is, however, just a copy of a reference hold under x variable from method named Main.

To actually change the text hidden under x variable, use the ref modifier (you have to set it both in the method declaration and its invocation - C# enforces such behavior for clarity):

using System;
               
class Program
{
    static void Test(ref string y)
    {
        y = "bbb";
    }

    static void Main()
    {
        string x = "aaa";
        Test(ref x);
        Console.WriteLine(x);
    }
}

After this change, console will show bbb text.

 

SOS

Way in which parameters are passed to a method can be examined by using tool called SOS (Son of Strike). We will use CLRStack -a command, which displays information about parameters and local variables on managed code stack (if you don't know how to use SOS look here and here, if you wonder where the name "Son of Strike" came from, click here)...

Below are the results of CLRStack -a command executed at the time of entry to the Test method.

For code without ref modifier:

!CLRStack -a
OS Thread Id: 0x176c (5996)
Child SP IP       Call Site
0031f114 00390104 Program.Test(System.String)
    PARAMETERS:
        y (0x0031f114) = 0x025cb948

0031f158 003900af Program.Main()
    LOCALS:
        0x0031f158 = 0x025cb948

0031f3c0 656721bb [GCFrame: 0031f3c0]

For code with ref modifier:

!CLRStack -a
OS Thread Id: 0x934 (2356)
Child SP IP       Call Site
001dee34 002f00f4 Program.Test(System.String ByRef)
    PARAMETERS:
        y (0x001dee34) = 0x001dee78

001dee78 002f00aa Program.Main()
    LOCALS:
        0x001dee78 = 0x027fb948

001df0ec 656721bb [GCFrame: 001df0ec]

An important difference that is exhibited by these results is the value of y parameter. In the case of code without ref modifier, it is the address of aaa string (0x025cb948). For the code with ref modifier, the value of y parameter is the address of x variable (0x001dee78) from Main method (that variable points to aaa string).

View State for TextBox and other controls that implement IPostBackDataHandler

While reading the official training kit for 70-515 exam I came across this text: "With view state, data is stored within controls on a page. For example, if a user types an address into a TextBox and view state is enabled, the address will remain in the TextBox between requests.". If such statements can be found in recommended study guide, it should not come as a surprise, that confusion about the way ASP.NET Web Forms tries to cope with inherent statelessness of HTTP is so common… ;)

TextBox control from ASPX page:

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

is rendered on HTML page as an input tag:

<input name="TextBox1" type="text" id="TextBox1" />

If so, then the preservation of TextBox value between requests does not require any use of __VIEWSTATE hidden field. To illustrate this, create a simple page that contains TextBox and Button controls:

...
 
<body>
    <form id="form1" runat="server">
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /
    </form>
</body>
</html>

and add a handler for button’s Click event, which only task is to extend the text in TextBox1 control:

protected void Button1_Click(object sender, EventArgs e)
{
    TextBox1.Text += "X";
}

Then, run the page and activate a tool for monitoring communication between browser and server. We are interested in testing form data that is sent to the server at postback... If you are using IE, I can recommend you a debugging proxy called Fiddler. Under Firefox, use Firebug. You can also use built-in ASP.NET Trace feature – to do so, add Trace = "true" to @Page directive. I performed my tests using development tools provided with Chrome browser ("Network" tab).

The following screenshot shows what form data (HTTP POST request) was sent after first button press:

Dane formularza przy pierwszym postbacku

And here is data from second postback:

Dane formularza przy drugim postbacku

If you compare data from first and second requests, you will see that a change in the value of TextBox1.Text does not affect the value of __VIEWSTATE field. Expanding the field would be a waste of network resources if text is being sent to server in a separate field called TextBox1.

System.Web.UI.WebControls.TextBox class is one of several classes that implement IPostBackDataHandler interface. This interface requires LoadPostData method. After page initialization is completed (but before the Load event) loading of View State data is invoked (LoadViewState) and then (if the control implements IPostBackDataHandler), loading of form data is invoked (LoadPostData). Text property of a TextBox control can therefore be set even if View State mechanism is disabled (via EnableViewState = "false" setting).

So... Can we completely disable View State mechanism for TextBox controls and the like?

No. For example, View State is useful when TextChanged event is handled (for comparison between current and previous value). It can also be used when the value that is being set is other than the one related to control’s value (e.g. ForeColor).