Thursday, November 19, 2009

Draw rotated text in VB/ASP.NET using the Matrix class

While working on 2D drawings in VB.NET, you might find yourself in a situation where you may want to rotate a text or any other object on the drawing canvas. I discovered this technique when I was trying to draw my text vertically from bottom to top and the System.Drawing.StringFormat class’s built in vertical text format would only support top to bottom layout. Then I discovered the System.Drawing.Drawing2D.Matrix class which is used for geometric transformation. Using the Matrix class you can rotate the drawing canvas to any desired angle, draw the text/object and then rotate it back to the original position.

Example of rotated text:
Rotated text in VB .NET

I have implemented the drawing by using ASP.NET web application where the drawing is generated by an aspx page. To view the image in web browser, you just need to create an HTML image tag on a new page and set the image source(src) to the .aspx file. The .aspx file code to generate a sample PNG file is given below. The main functionality for rotating the text is implemented in the RotateString subroutine which is provided with the text, rotation angle, and the x and y coordinates.

Imports System.Drawing
Imports System.IO
Imports System.Drawing.Drawing2D

Partial Public Class TextImageDraw
    Inherits System.Web.UI.Page

    'Dimensions of the bitmap
    Const DRAWING_HEIGHT As Integer = 300
    Const DRAWING_WIDTH As Integer = 300

    Dim bitmap As New Bitmap(DRAWING_WIDTH, DRAWING_HEIGHT)
    Dim myDrawing As Graphics = Graphics.FromImage(bitmap)

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim myDrawingBackgroundColor As New SolidBrush(Color.AliceBlue)
        'Fill Drawing Background
        myDrawing.FillRectangle(myDrawingBackgroundColor, 0, 0, DRAWING_WIDTH, DRAWING_HEIGHT)

        myDrawing.TextRenderingHint = Text.TextRenderingHint.AntiAlias

        Dim myText As String = "   web3o.blogspot.com"

        'Text Rotation Cordinates
        Dim xCordinate As Integer = DRAWING_WIDTH / 2
        Dim yCordinate As Integer = DRAWING_HEIGHT / 2

        'Draw Rotation Center
        myDrawing.DrawEllipse(Pens.Black, New Rectangle(xCordinate - 1, yCordinate - 1, 3, 3))

        'Draw Header Text
        Dim headingText As String = "Rotating Text"
        Dim headingFont As Font = New Font("arial", FontSize.XLarge, FontStyle.Regular)
        Dim headingTextWidth As Double = myDrawing.MeasureString(headingText, headingFont).Width
        Dim headingTextHeight As Double = myDrawing.MeasureString(headingText, headingFont).Height
        myDrawing.DrawString(headingText, headingFont, Brushes.Red, _
                             (DRAWING_WIDTH - headingTextWidth) / 2, 2)

        'Draw Text in 360 degrees with 30 degree interval
        For angle = 0 To 330 Step 30
            RotateString(myText, angle, xCordinate, yCordinate)
        Next

        'Draw Footer Text
        myDrawing.DrawString(headingText, headingFont, Brushes.Red, _
                            (DRAWING_WIDTH - headingTextWidth) / 2, _
                            DRAWING_HEIGHT - headingTextHeight - 2)

        'Set smoothing mode for the drawing to Anti-alias
        myDrawing.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

        'Write the image to browser...
        Response.ClearContent()
        Response.ContentType = "image/png"
        Dim mem As New MemoryStream()
        bitmap.Save(mem, System.Drawing.Imaging.ImageFormat.Png)
        mem.WriteTo(Response.OutputStream)
        myDrawing.Dispose()
        bitmap.Dispose()
    End Sub

    Private Sub RotateString(ByVal Text As String, ByVal angle As Integer, _
                             ByVal x As Integer, ByVal y As Integer)
        Dim myFont As Font = New Font("arial", FontSize.XLarge, FontStyle.Regular)
        Dim myColor As SolidBrush = New SolidBrush(Color.Black)
        ' Make a rotation matrix
        Dim myMatrix As New Matrix
        myMatrix.RotateAt(angle * -1, New Point(x, y)) 'Rotate drawing
        myDrawing.Transform = myMatrix
        myDrawing.DrawString(Text, myFont, myColor, x, y) 'Draw the text string
        myMatrix.RotateAt(angle, New Point(x, y)) 'Rotate back
        myDrawing.Transform = myMatrix
    End Sub

End Class

You can just copy the RotateString subroutine to your code and pass the Graphics class object along with other parameters to draw the rotated string on it.

Multiple File Uploads in ASP.NET with Add/Remove and Up/Down functionalities

HTML or ASP.NET does not allows you to select more then one file in a single file upload input field. To work around this shortcoming you will either have to add dynamic file upload fields by using JavaScript or use a single file upload field to upload the files one by one.

I have devised a nifty technique by using the ASP.NET ListBox control to keep track of the added files and manage them. You can add/remove or change the upload order of the files before uploading them all to your server/database. Sometimes the order of your file upload is also very important and it becomes more easier with this technique where you can arrange them by using the Up/Down controls.

Multiple File Uploads in ASP.NET

The code for the .aspx file is pretty straight forward with a FileUpload control, a ListBox control and buttons to handle all the functionalities. You can even implement this code as an ASP.NET User Control for your project.

Here is the File Upload code for .aspx file:
<table>
<tr>
    <td colspan="2">
    <font color="red"><asp:Label ID="Message" runat="server" Text=""></asp:Label></font>
    </td>
</tr>
<tr>
    <td colspan="2">
    <asp:FileUpload runat="server" id="FileUploader" Width="300"></asp:FileUpload>
    </td>
</tr>
<tr>
    <td>
    <asp:ListBox ID="FileListBox" runat="server" Width="300" Rows="5" SelectionMode="Single" BackColor="AliceBlue">
    </asp:ListBox>
    </td>
    <td>
    <asp:Button ID="Up" runat="server" Text="&uarr;" Font-Bold="true" Font-Size="Large" /><br />
    <asp:Button ID="Down" runat="server" Text="&darr;" Font-Bold="true" Font-Size="Large" /><br />
    </td>
</tr>
<tr>
    <td colspan="2">
    <asp:Button ID="Add" runat="server" Text="Add" />
    <asp:Button ID="Remove" runat="server" Text="Remove" />
    <asp:Button ID="Upload" runat="server" Text="Upload" />
    </td>
</tr>
</table>
<br /><br />
<asp:Literal ID="FileList" runat="server"></asp:Literal>

The backend code in VB is also pretty easy to understand with subroutines to handle the button click events. To keep track of all the files added to the list we use a Listbox control and to store the HttpInputFile objects we use a global ArrayList named Files. For saving the files I have used an example of storing the files in a Database using stored procedure, but you can always save the file to your server itself by using the HIF.PostedFile.SaveAs method. Detailed description for the functionality of each button click event subroutine is given below:

  • Add_Click: Fires when the user browses a file and click on the Add button. Error checking is done to ensure if the FileUpload control has input file, if the file size is not zero and does the file already exists in the list or not. After error checking is passed, the file name is added to to List Box and also to the global ArrayList which holds the object to the HttpInputFile class.
  • Remove_Click: This subroutine simply removes the file name at selected index from the List Box and from the Files Array.
  • Up_Click: The position of the selected item is switched with the item on top of it in the List Box and the Array List.
  • Down_Click: The position of the selected item is switched with the item below it in the List Box and the Array List.
  • Upload_Click: All the files in the Files Array are uploaded to the database using stored procedure.

Here is the VB file code for the File Uploader:

Imports System.Data.SqlClient

Partial Public Class _Default
    Inherits System.Web.UI.Page

    Public Shared Files As ArrayList = New ArrayList()
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    End Sub

    Protected Sub Add_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Add.Click
        Try
            Message.Text = ""
            If FileUploader.HasFile Then 'Check if file exists...
                If FileUploader.PostedFile.ContentLength > 0 Then 'Check file size
                    If FileListBox.Items.Contains(New ListItem(System.IO.Path.GetFileName(FileUploader.PostedFile.FileName))) Then
                        Message.Text = "File already in the list!"
                    Else
                        Files.Add(FileUploader)
                        FileListBox.Items.Add(System.IO.Path.GetFileName(FileUploader.PostedFile.FileName))
                        Message.Text = "Add another file or click Upload to save them all..."
                    End If
                Else
                    Message.Text = "File size cannot be 0!"
                End If
            Else
                Message.Text = "Please select a file to add!"
            End If
        Catch ex As Exception
            ' Handle Error
        End Try
    End Sub

    Protected Sub Remove_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Remove.Click
        If FileListBox.Items.Count > 0 Then
            If FileListBox.SelectedIndex < 0 Then
                Message.Text = "Please select a file to remove!"
            Else
                Files.RemoveAt(FileListBox.SelectedIndex)
                FileListBox.Items.Remove(FileListBox.SelectedItem.Text)
                Message.Text = "File removed..."
            End If
        End If
    End Sub

    Protected Sub Up_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Up.Click
        If FileListBox.Items.Count > 1 AndAlso FileListBox.SelectedIndex > 0 Then
            Dim index As Integer = FileListBox.SelectedIndex
            Dim toMove As String = FileListBox.SelectedValue
            'Move up filename in ListBox
            FileListBox.Items.Insert(index - 1, toMove)
            FileListBox.Items.RemoveAt(index + 1)
            FileListBox.Items.Item(index - 1).Selected = True
            'Move up file in Files ArrayList
            Dim TempFileHandle As FileUpload = Files(index - 1)
            Files(index - 1) = Files(index)
            Files(index) = TempFileHandle
        End If
    End Sub

    Protected Sub Down_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Down.Click
        If FileListBox.Items.Count > 1 AndAlso FileListBox.SelectedIndex < FileListBox.Items.Count - 1 Then
            Dim index As Integer = FileListBox.SelectedIndex + 1
            Dim toMove As String = FileListBox.Items.Item(index).Text
            'Move down filename in ListBox
            FileListBox.Items.Insert(index - 1, toMove)
            FileListBox.Items.RemoveAt(index + 1)
            FileListBox.Items.Item(index).Selected = True
            'Move down file in Files ArrayList
            Dim TempFileHandle As FileUpload = Files(index - 1)
            Files(index - 1) = Files(index)
            Files(index) = TempFileHandle
        End If
    End Sub

    Protected Sub Upload_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Upload.Click
        Dim conn As SqlConnection = New SqlConnection("")
        conn.Open()
        For Each HIF As FileUpload In Files
            FileList.Text += "Uploading file: " & HIF.PostedFile.FileName + "<br />" + vbCrLf
            Dim fileBytes(HIF.PostedFile.InputStream.Length) As Byte
            HIF.PostedFile.InputStream.Read(fileBytes, 0, fileBytes.Length)
            Dim Command As New SqlCommand
            With Command
                .Connection = conn
                .CommandType = CommandType.StoredProcedure
                .CommandText = "upload_files"
                .Parameters.AddWithValue("@id", System.Guid.NewGuid.ToString())
                .Parameters.AddWithValue("@name", System.IO.Path.GetFileName(HIF.PostedFile.FileName))
                .Parameters.AddWithValue("@size", HIF.PostedFile.ContentLength)
                .Parameters.AddWithValue("@type", HIF.PostedFile.ContentType)
                .Parameters.AddWithValue("@file", fileBytes)
                .Parameters.AddWithValue("@dateadded", DateTime.Now())
            End With
            Command.ExecuteNonQuery()
        Next
        conn.Close()
        Message.Text = ""
        'Clear Files ArrayList
        Files.Clear()
        'Clear File List Box
        FileListBox.Items.Clear()
    End Sub
End Class

This implementation contains very minimal amount of code to attain the desired functionalities, you can always add more error checking or styles to suit your website design.

Friday, November 13, 2009

Making Checkboxes behave like Radio Buttons using jQuery

Sometimes you might need Checkboxes to behave like Radio Buttons on your webpage because you may only want zero or one selection from a category of choices. You cannot select 0 or 1 choice from a Radio Button Group because Radio Button groups are meant to select only one choice from a group.

I have written an easy to use and understand code in jQuery for achieving this task. In this example, all the checkboxes with name Colors are assigned a click function (Checkbox_to_RadioButton()) when the page loads for the first time. The Checkbox_to_RadioButton() is a generic function which will automatically uncheck all other other checkboxes with the same name/group.

Too make this work on your page, you just need to paste this JavaScript code in the head section of your webpage and set the Checkbox group name in the page ready function.

JavaScript Code:
<script type="text/javascript" src="http://jqueryui.com/latest/jquery-1.3.2.js"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('input:checkbox[name=Colors]').click(function(){
            Checkbox_to_RadioButton(this);
      });
});
function Checkbox_to_RadioButton(box){
      $('input:checkbox[name=' + box.name + ']').each(function(){
            if (this != box) $(this).attr('checked', false);
      });
}
</script>

HTML Code:
<input type="checkbox" name="Colors" value="Red" />Red<br />
<input type="checkbox" name="Colors" value="Blue" />Blue<br />
<input type="checkbox" name="Colors" value="Green" />Green<br />
<input type="checkbox" name="Colors" value="Yellow" />Yellow<br />

Friday, September 18, 2009

jQuery Animated Tree Menu

Tree Menu is another important form of navigation menu and is used widely where the content has to be organized in a tree or windows folder like structures. To design our Tree Menu we’ll be using simple unordered lists in HTML and the power of jQuery to animate it. With little CSS trick I have implemented 2 different styles of tree, one by placing the node icon at branch end and second by placing node icon at branch bifurcation.

Benefits of using this Tree Menu:

  1. Zero coding required.
  2. jQuery based Menu compliant with all the browsers.
  3. Easy to manipulate jQuery code.
  4. Functionality for Expanding, Contracting, and Toggling the nodes in one click.
  5. Choose between 2 different styles just by editing only two lines in CSS code.
  6. Minimal CSS used which you can modify based upon your preferences.

This is how the two styles look like:

jQuery Tree Menu jQuery Tree Menu
Style 1: Node icon at branch end. Style 2: Node icon at branch division.

 

Download other images used for tree branch and nodes (click on image to open in new window):

plus minus blank branch
plus.gif minus.gif blank.gif branch.png

Using the mighty power of jQuery, performing tedious operation on HTML DOM elements like selection and animation just becomes more and more easy. Using jQuery this task has been accomplished in less then 10 lines whereas in traditional JavaScript it would have taken up close to 100 lines. I have used nested unordered lists (ul) inside list items (li) to create child tree’s so I’ve implemented jQuery selection wrapper as li:has(ul) to select all li nodes with children ul. The JavaScript code is pretty easy to understand, initially when the page loads the tree is initialized as follows:

  1. All tree nodes with children ($('.tree li:has(ul)')) are assigned the plus node icon and all the child nodes are hidden initially.
  2. A click event is assigned to all nodes with children ($('.tree li:has(ul)')). Click event uses the toggle function to show/hide the children of any node and change node icons.
  3. All leaf nodes ($('.tree li:not(:has(ul))')) are assigned blank node icon.
  4. Every last child’s ($('.tree li:last-child')) background images is changed to give the branch ending effect.

Apart from the initialization function I’ve also provided functions for single click Expansion, Contraction and Toggling of Tree nodes. jQuery’s show and hide functions are used to show/hide the children. The toggling and show/hide speeds can be set to ‘slow’, ‘normal’, or ‘fast’.

Put the following JavaScript code in the head section of your page.
JavaScript Code:
<script type="text/javascript" src="http://jqueryui.com/latest/jquery-1.3.2.js"></script>
<script type="text/javascript">
//Developed By: Abhinay Rathore
//Blog: web3o.blogspot.com

$(function(){ //initialize Tree Menu when page loads...
      //For all nodes with children under tree: hide all child nodes initially and change list image
      $('.tree li:has(ul)').css({cursor:'pointer','list-style-image':'url(plus.gif)'}).children().hide();
      //Assign Click event to all nodes with children
      $('.tree li:has(ul)').click(function(event){
            if (this == event.target) { //if target element of the event matches 'this'
              //toggle list image and show/hide children using toggle('fast') method
              $(this).css('list-style-image', ($(this).children().is(':hidden')) ? 'url(minus.gif)' : 'url(plus.gif)');
              $(this).children().toggle('fast');
            }
            return true;
      });
      //For all nodes with no children: change list image to blank
      $('.tree li:not(:has(ul))').css({cursor: 'pointer','list-style-image':'url(blank.gif)'});
      //Change Background image for every last child
      $('.tree li:last-child').css({'background':'url(branch.png) 0px -1970px no-repeat'});
});
//Expand all tree nodes
function ExpandTree(){
      $('.tree li:has(ul)').css('list-style-image', 'url(minus.gif)');
      $('.tree li:has(ul)').children().show('fast');
}
//Contract all tree nodes
function ContractTree(){
      $('.tree li:has(ul)').css('list-style-image', 'url(plus.gif)');
      $('.tree li:has(ul)').children().hide('fast');
}
//Toggle all tree nodes
function ToggleTree(){
      $('.tree li:has(ul)').click();
}
</script>

I have created this Tree Menu with minimal CSS required. You can add extra styling to match the color and styling of your website. For switching between the two styles shown above, you can make the appropriate changes in the CSS as shown in comments below. If you want to change the font size or margins on the tree nodes, you might have to adjust the CSS along with the branch image provided in this post.

CSS Code:
<style type="text/css">
<!--
.tree {
      font-family: Verdana, Geneva, sans-serif;
      font-size: small;
      margin: 10px; padding: 0px;
}
.tree ul { margin: 0px; padding: 0px; } /* Disable this for 2nd Style */
.tree li {
      padding: 5px 0 1px 30px; /* Use this for 1st Style */
      /*padding: 5px 0 1px 10px; /* Use this for 2nd Style */
      margin: -3px 0px 0px -10px;
      background: url(branch.png) 0px 0px no-repeat;
      list-style-position: inside;
}
.tree a{
      text-decoration: none;
}
-->
</style>

The HTML code for the Tree Menu only consists of unordered list or items nested inside each other. Every list item (li) is considered a leaf node unless another unordered list (ul) is nested inside it. You can either use links or text inside list items. There is no restriction on the depth of the tree. I have also provided 3 links as examples on top to use for the one-click toggling functions.

HTML Code:
<a href="javascript:ExpandTree()">Expand All</a> |
<a href="javascript:ContractTree()">Contract All</a> |
<a href="javascript:ToggleTree()">Toggle All</a>

<ul class="tree">
    <li>Item 1
      <ul>
            <li><a href="#">Item 1.1</a></li>
      </ul>
    </li>
    <li>Item 2
      <ul>
            <li><a href="#">Item 1.1</a></li>
            <li><a href="#">Item 1.2</a></li>
      </ul>
    </li>
    <li>Item 3
        <ul>
            <li><a href="#">Item 3.1</a></li>
            <li>Item 3.2
                <ul>
                    <li><a href="#">Item 3.2.1</a></li>
                    <li><a href="#">Item 3.2.2</a></li>
                    <li>Item 3.2.3
                        <ul>
                            <li><a href="#">Item 3.2.3.1</a></li>
                            <li><a href="#">Item 3.2.3.2</a></li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li><a href="#">Item 3.3</a></li>
      </ul>
    </li>
    <li>Item 4
          <ul>
          <li><a href="#">Item 4.1</a></li>
          <li>Item 4.2
              <ul>
                  <li><a href="#">Item 4.2.1</a></li>
                  <li><a href="#">Item 4.2.2</a></li>
              </ul>
          </li>
          </ul>
    </li>
    <li>Item 5
      <ul>
            <li><a href="#">Item 5.1</a></li>
            <li><a href="#">Item 5.2</a></li>
      </ul>
    </li>
</ul>

Looking at the Tree Menu code above and comparing it with the functionality it provides, you must have realized the power of jQuery which make HTML DOM selection and event handling so seamless and easy to use.

del.icio.us Tags: ,,