Dec 25 2009

C# – Alternative to overriding static variables

Tag: .NET, C#, ProgrammingAbhijeet Maharana @ 9:22 pm

In a recent project, I came across a peculiar requirement.

Modified version of the requirement:
1. Define a static variable in base class (say Code)
2. Define a property in base class that accesses Code (say Message)
3. Modify the value of Code in derived class
4. BaseInstance.Message should access the value of Code defined in base class whereas DerivedInstance.Message should access the one defined in derived class.

So I tried the following

namespace StaticTest
{
    class Base
    {
        protected static int Code = 1;
 
        public String Message
        {
            get
            {
                switch (Code)
                {
                    case 1:
                        return "One";
 
                    case 2:
                        return "Two";
 
                }
 
                return "Default";
            }
        }
    }
 
    class Derived : Base
    {
        protected static new int Code = 2;
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Base.Message: " + new Base().Message);
            Console.WriteLine("Derived.Message: " + new Derived().Message);
 
            Console.Read();
        }
    }
}

This did not work and the output was

Base.Message: One
Derived.Message: One

Turns out that Message needs to be redefined in Derived to be able to access the new value of Code. With a lot of derived classes, this was impractical and Message’s getter was a bit more involved than what I have written above.

I found a neat solution by Dave Booker posted here.

Define a custom attribute class

[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class CodeAttribute : Attribute
{
        public int Code;
        public CodeAttribute(int code)
        {
            Code = code;
        }
}

Then define attribute values for the 2 classes:

[CodeAttribute(1)]
class Base
{ ... }
 
[CodeAttribute(2)]
class Derived
{ ... }

Now delete the Code property from the classes and modify Message to retrieve the code like this:

public String Message
{
	get
        {
                int Code = ((CodeAttribute) Attribute.GetCustomAttribute(this.GetType(), typeof(CodeAttribute))).Code;
 
                switch (Code)
                {
                    case 1:
                        return "One";
 
                    case 2:
                        return "Two";
 
                }
 
                return "Default";
         }
}

This returned the values as expected. If the derived class is not supplied with an attribute value, it just inherits the value from its parent. So not exactly a static variable but it behaves like one that can be inherited and overriden if necessary. Quite elegant!

The original requirement was to eliminate any instances of both classes. This meant Message had to be a static property. I haven’t been able to figure out how to do that … specifically how to replace “this.GetType()” with something static that returns which class the property was invoked with rather than the class which it was defined in (which is what the reflection based methods do).

Any ideas? Other than getting into IL code to see if and how this can be done?


Mar 14 2009

OpenGL workshop and nostalgia

Tag: Workshops/SeminarsAbhijeet Maharana @ 8:57 pm

I conducted a workshop on OpenGL today. It was in the same college where I completed my Engineering, SFIT Borivali. I had done it for the first time in 2003. And I remember how nervous I was because I was in the 2nd year and almost everyone who participated was a senior! Although everyone was from 2nd year this time, it wasn’t much different. I was as nervous when I started off because I had done this 3 years back and couldn’t go through the content even once. However I had saved all the material used earlier and this saved me lots of time.

I was nostalgic all the time. Same college, same labs, not the same machines but I had worked on these machines before moving out. Brought back all those memories. All new faces but the same curiosity which made me spend an entire semester struggling to figure out how VC++ 6 is different from Turbo C and why Turbo C won’t compile the OpenGL programs that I had downloaded! And how GLUT came to my rescue before my curiosity died while meddling with the Windows API! In the rush to make a living by working on stuff that the industry pays for, that curiosity has had to take a backseat after I got out from college. But it felt very nice to get back after such a long time! If someone could pay for my material needs while I did this, nothing like it!

Ajesh came along to help the participants. Thanx a ton man! He clicked a few snaps. Ill put them up in the wokshops section. Now back to the present and back to the task at hand :)


Dec 12 2008

Override rendering of column from SmartGWT data source

Tag: Gwt, Java, Programming, smartgwtAbhijeet Maharana @ 10:17 pm

SmartGWT widgets can render themselves sensibly using the data source definition. So for a grid, we don’t need to define the columns explicitly. However, we can override the rendering of some or all columns as needed.

Assume that our data source and data looks like this:

class CompanyDataSource extends DataSource {
	public CompanyDataSource(String id) {
		setID(id);
 
		DataSourceTextField companyName = new DataSourceTextField("company", "Company");
		DataSourceFloatField price = new DataSourceFloatField("price", "Price");
		DataSourceDateField lastChanged = new DataSourceDateField("lastChanged", "Last Changed");
		setFields(companyName, price, lastChanged);
	}
}
"3m Co", "71.72", "9/1 01:25 AM"

And the grid that renders this data

DataSource dataSource = new CompanyDataSource(“companyList1”);
dataSource.setClientOnly(true);
 
ListGrid companyGrid = new ListGrid();
companyGrid.setHeight(300);
companyGrid.setWidth(500);
companyGrid.setTitle("SmartGWT grid");
companyGrid.setDataSource(dataSource);
companyGrid.setAutoFetchData(true);

To override the display format of lastChanged column, one approach would be

ListGridField lastChangedField = new ListGridField("lastChanged", "Last Changed (new title)", 180);
CellFormatter dateFormatter = new CellFormatter(){
	public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
 
		DateTimeFormat inputFormat = DateTimeFormat.getFormat("d/M hh:mm a");
		DateTimeFormat outputFormat = DateTimeFormat.getFormat("MMM dd HH 'hours' mm 'minutes'");
		Date inputDate = inputFormat.parse(value.toString());
		String output = outputFormat.format(inputDate);
 
		return output;
	}
};
 
lastChangedField.setCellFormatter(dateFormatter);
companyGrid.setFields(lastChangedField);

We define a ListGridField with the same name “lastChanged” as in the data source. SmartGWT will use this name to do the merge. Our custom cell formatter matches the input date format and returns it in a different format.

But now the grid will only display this field. To cause it to display other data source fields as they are, we need to call

companyGrid.setUseAllDataSourceFields(true);

We can also override the date format in the data source itself so that all widgets sourcing this data will reflect it. As I was thinking about this, I came across this post on the SmartGWT forums. The API will support this functionality soon and as that thread also mentions, for formatting dates, you can use ListGrid.setDateFormatter() and DateItem.setDisplayFormat().

Thats it for this time. Ill keep posting tidbits as I learn along the way.


Dec 07 2008

GWT-Ext Store to SmartGWT DataSource

Tag: Ext, Gwt, Java, Programming, smartgwtAbhijeet Maharana @ 2:18 am

GWT-Ext Store instances are all over my code. And I am populating them by various means. While migrating from GWT-Ext to SmartGWT, converting Stores to DataSources will probably take up a lot of time. I was wondering if I could migrate and test only the grids first and deal with the stores later. Code below could help do just that. It creates a DataSource from a Store. You can use this data source to populate SmartGWT grids and when the grids are working fine, replace the stores completely. Isn’t exactly a life saver but nevertheless. Have tested it only on a trivial store.

It doesn’t matter but assume that the RecordDef used to create the Store looks like this:

RecordDef recordDef = new RecordDef(new FieldDef[] {
	new StringFieldDef("company"), 
	new FloatFieldDef("price"),
	new FloatFieldDef("change"), 
	new FloatFieldDef("pctChange"),
	new DateFieldDef("lastChanged", "n/j h:ia"),
	new StringFieldDef("symbol"), 
	new StringFieldDef("industry") 
});

Create a DataSource with the same fields:

private DataSource createDataSource(Store store){
	DataSource dataSource = new DataSource();
	dataSource.setClientOnly(true);
 
	String[] fields = store.getFields();
	for(String field:fields) {
		DataSourceField smartgwtField = new DataSourceField();
		smartgwtField.setName(field);
		dataSource.addField(smartgwtField);
	}
	return dataSource;
}

Add a method that copies records from the Store to the data source created above and call it in the Store’s onLoad handler

public void copyStore(Store store, DataSource dataSource) {
	Record[] records = store.getRecords();
	String[] fields = store.getFields();
 
	for(Record gwtextRecord:records) {
		ListGridRecord smartgwtRecord = new ListGridRecord();
		for(String field:fields) {
			smartgwtRecord.setAttribute(field, gwtextRecord.getAsString(field));
		}
		dataSource.addData(smartgwtRecord);
	}
}

For heavy stores, this code will probably punish the browser and column data types are ignored as well but it is meant only for the dev environment until all components have been replaced eventually.

PS: If you need it, here is a small sample with GWT-Ext and SmartGWT grids being populated from the same RPC method. You will need to add gwtext.jar and smartgwt.jar and use Cypal studio plugin or add compile/run scripts.


Nov 29 2008

Trac on Windows

Tag: Project Management, PythonAbhijeet Maharana @ 3:34 am

I needed to install Trac on my laptop. Trac is an enhanced wiki and issue tracking system for software development projects. I had used it about 2 years back and had liked it then. However, I had never installed it myself. I assumed it will be like any other installation. But just after starting out, I realized that I was grossly mistaken. Installing Trac and getting it running with the webadmin plugin and users configured for your projects is a little more than a post-work headache.

I have the following setup:

  • OS: Vista business 32-bit
  • Python: Not already installed on my system

After installation, we will be running Trac 0.10.4 with webadmin plugin and users configured for a project. This installation will be running on Apache and we won’t be using Trac’s standalone webserver (tracd). I am not using Trac’s subversion feature since I am already running VisualSVN server (and I love its ease of use). Ill try to switch sometime later if thats not another royal pain.

It turns out that the steps are quite simple … if you happen to know them.

  • Install Bitnami Trac stack

    Bitnami’s stacks are very handy. They take care of the dependencies required for a piece of software to run. So this will take care of Python, sqlite database and Apache for us. For Trac 0.10, the webadmin plugin needs to be installed separately. 0.11 includes it in the core package itself. However, Bitnami’s stack hasn’t been upgraded yet.

    While installing the Trac stack, select yes when prompted to create a project and provide the details. I will assume installation at “C:\Program Files\BitNami Trac Stack” and first project as Project1.

  • Install webadmin plugin

    Download from the link that says “Download for Trac 0.9.3 or later (Python 2.4)”. (despite the notice that says for 0.10.x, you must build from SVN). After downloading it, remove the .zip extension and drop the resulting .egg file in C:\Program Files\BitNami Trac Stack\projects\Project1\plugins. This will install the webadmin plugin so that we don’t have to resort to the command line every now and then. The plugin will be installed only for this project. To install it for all projects, follow the instructions here.

  • Create users

    Wait, the webadmin plugin doesn’t allow you to create users! Trac uses the authentication provided by the web server. In our case, we need to create users for Apache. We can then assign roles to these users via the Trac webadmin interface.

    Navigate to C:\Program Files\BitNami Trac Stack\trac\conf and locate the htpasswd file. This file holds the usernames and passwords. Bitnami makes the appropriate configuration changes to have Apache authenticate users against this file. Users added to this file will be available across all your projects. For adding a user “abhijeet” to this file, open a command prompt, cd to C:\Program Files\BitNami Trac Stack\apache2\bin and execute the command:

    htpasswd "C:\Program Files\BitNami Trac Stack\trac\conf\htpasswd" abhijeet

    Supply the password when prompted and the new user should be created.

  • Assign roles and permissions

    Restart “tracApache” service from the Windows Services management console and verify that you can login using the newly created username. For assigning permissions to this user, login again as the admin user using the password you supplied during installation. Locate the admin link near the top right corner and click on Permissions on the left. Add a group “developer” and grant permissions for the same. Then add your developers to this group. A screenshot could help (I have edited this image. It was too wide).

You should have the Trac installation running now. Backup is as simple as creating a copy of the “projects” folder. If you can’t see the admin link on the upper right corner after all this, be prepared to spend the night getting it to show up. Start here!

Finally, if you have any Trac tips up your sleeve, I would love to read them. Things such as setting up multiple projects, having different sets of users for projects …



Nov 27 2008

Mumbai 26/11

Tag: UncategorizedAbhijeet Maharana @ 2:00 am

Update (27/11): Help Mumbai page with all relevant phone numbers: http://helpmumbai.pinstorm.com/

There is a lot of trouble in Mumbai, India right now. There are terrorists throughout the city and if you switch the television on at this moment (2 AM), you will lose your nerves. If you want to touchbase with your dear ones here but are not able to get through, leave a message with your and your friend’s numbers. I will try to get through to them as frequently as I can. If you are in Mumbai and can help folks, try and answer the queries here or leave your number here.

Blood needed at various hospitals (source: IBN live stream):
St. George’s hospital: (022) 22620242
JJ Hospital: (022) 23739031

CNN IBN Live Streaming: http://tinyurl.com/644733
DFAT emergency number: 1300 555 135 (via @AnneBB)
http://twitter.com/squorch/status/1025372562
http://twitter.com/Asfaq/statuses/1025385789
Mumbai police telephone numbers: http://www.mumbaipolice.org/imp_telnfax.htm
Wikipedia article: http://en.wikipedia.org/wiki/26_November_2008_Mumbai_attacks

Update: There are people at MumbaiHelp who can help as well http://mumbaihelp.blogspot.com/2008/11/can-we-help.html


Nov 19 2008

SmartGWT 1.0

Tag: Gwt, Web, smartgwtAbhijeet Maharana @ 1:45 am

SmartGWT 1.0, a web application library based on SmartClient and GWT, was released this Monday. From the release announcement at Sanjiv’s blog and the showcase demos, it is evident that this library packs a lot of power and is definitely worth checking out. I have come across SmartClient only recently. And now that I know of it, Ill try and get acquainted with it when I can.

Links:
SmartClient: http://www.smartclient.com/
SmartGWT: http://code.google.com/p/smartgwt/
Visual Builder videos: http://www.smartclient.com/technology/visualbuilder.jsp


Oct 26 2008

Google chat and FoxClocks

Tag: Chat, Firefox, WebAbhijeet Maharana @ 11:13 pm

Google Chat

It once happened that I did not recollect adding someone on GTalk and yet the contact showed up in my buddy list. I thought maybe the other guy did and that I forgot about it after accepting the request. Then it started happening very frequently and I had no clue.

Well, it turns out that if you communicate frequently with some people, GMail automatically allows them to chat with you and see when you are online. Its great to make new friends and learn from new people but sometimes, its just better to know who is on your buddy list! To turn this otherwise helpful feature off, log into your Gmail account and go to Settings >> Chat. Select “Only allow people that I’ve explicitly approved to chat with me and see when I’m online.”


FoxClocks

If you work across timezones, you will probably agree that having to remember / calculate the time at your client’s end isn’t always a fun thing to do. I had a couple of Timezone widgets added to my iGoogle page but I didn’t find them compelling. Just last week, I noticed Andy McDonald’s FoxClocks as a recommended extension on the Firefox add-on page. One look at the screenshot and I blinked only after it was installed. Needless to say, its a very well-made, unobtrusive extension which sits in the statusbar / toolbar and is right there when you need it. Highly customizable and highly recommended.


Oct 07 2008

GWT-Ext Combo helper method

Tag: Ext, Gwt, Java, Javascript, ProgrammingAbhijeet Maharana @ 10:25 pm

While working with a GWT-Ext application, I found that most of the Combo boxes used are just meant to be readonly drop down lists. Like the style 2 combo boxes we had in VB. A 2D array with display and value fields is all that is needed. Yet, every combo needs 6-7 lines to get going.

This utility method may be handy in such situations:

public static ComboBox getDropDownCombo(Object[][] data, String fieldLabel, String emptyText, int width, int listWidth)
{
	Store store = new SimpleStore(new String[]{"display", "value"}, data);
	ComboBox combo = new ComboBox();
	combo.setEditable(false);
	combo.setStore(store);
	combo.setDisplayField("display");
	combo.setValueField("value");
	combo.setMode(ComboBox.LOCAL);
	combo.setTriggerAction(ComboBox.ALL);
 
	if(fieldLabel != null)
		combo.setFieldLabel(fieldLabel);
	else
		combo.setHideLabel(true);
 
	if(width != -1)
		combo.setWidth(width);
 
	if(listWidth != -1)
		combo.setListWidth(listWidth);
 
	if(emptyText != null)
		combo.setEmptyText(emptyText);
	else
		// if there is no empty text, select the first value by default
		combo.setValue(data[0][1].toString());
 
	return combo;
}

Sample usage could be:

String[][] data = {{ "Mark as read", "1"}, {"Mark as unread", "2"}, {"Add star", "3"}, {"Remove star", "4"}};
ComboBox cmbMin = UIHelper.getDropDownCombo(data, "Actions", "[Select]", 275, -1);

Sep 28 2008

GWT-Ext and jQuery input mask plugin

Tag: Ext, Gwt, Java, Javascript, Programming, WebAbhijeet Maharana @ 1:59 am

Yesterday, while dabbling with jQuery and getting amazed by the wealth of plugins and effects available for this library, I came across http://digitalbush.com/2008/07/31/masked-input-plugin-114/. It allows you to fit text fields with an input mask to allow only fixed-width input in a certain format. I had seen it first in MS Access a long long time ago.

To use it with GWT-Ext, include jquery.js and jquery.maskedinput.js in your host HTML file. Use <script></script> and not <script/> to avoid wasting time later.

<script language = "javascript" type="text/javascript" src="js/jquery.js" ></script>
<script language = "javascript" type="text/javascript" src="js/jquery.maskedinput.js" ></script>

Now write some native code to call the plugin’s methods:

private native void addPlaceholder(String placeholder, String maskString) /*-{
	$wnd.$.mask.addPlaceholder(placeholder, maskString);
}-*/;
 
private native void mask(String id, String maskString, String placeholderString) /*-{
	if(placeholderString != null)
		$wnd.$('#' + id).mask(maskString, {placeholder:placeholderString});
	else
		$wnd.$('#' + id).mask(maskString);
}-*/;

Add the mask to a text field:

addPlaceholder("~", "[+-]");
textField.doOnRender(new Function(){
	public void execute() {
		mask(textField.getId(), "Rs. ~9999.99/-", " ");
	}
});

This will only allow values of the type “Rs. +2345.50/-” with “Rs. ” and “/-” already filled in for the user.

Update: See this: http://gwt-ext.com/forum/viewtopic.php?f=9&t=2984. Thanks mdeg and vanderbill!


Next Page »