Nowdays Im focused on Boxerp development in my spare time. The old 0.0.1 version is deprecated since I am rewriting the whole framework. Now I have powerful development tools which provide agile development, facilities, reliability and high performance. Desktop applications development using Gtk# is a better experience for me than web development. Iam really having fun writing the Gtk# client using MonoDevelop (Stetic GUI Designer).
In the server side, the ORM is the wonderful Castle.ActiveRecord which let me play with relational objects in a fancy way. Remoting is the communication technology, which let me send ActiveRecord models (relational objects) between client and server without problems (No circular reference problems). Furthermore, the CallContext avoids to send the session token in every remote call. However, there is a little problem with the CallContext because if I use independent threads I should manually pass the session token between them and I need different threads to keep the client application responsive. This is not very important, just one line of code.
The client code is clear thanks the Stetic designer. It uses XML to store the forms (is a Glade evolution) and the code is clean, it just contains the controller code, not widgets initializations neither something like that.
Look at the administrator’s main window file (at the moment it just loads data from server and shows them if login was correct because the ssession token is going to be sent in the CallContext):
using Gtk;
namespace administrator{
public class MainWindow : Gtk.Window{
protected MainHelper helper;
protected widgets.SimpleTreeView streeviewEnterprises;
protected widgets.SimpleTreeView streeviewUsers;
protected widgets.SimpleTreeView streeviewGroups;
public MainWindow () : base ( “”){
Stetic.Gui.Build(this, typeof (MainWindow));
helper=new MainHelper(refthis.streeviewEnterprises, refthis.streeviewUsers,
refthis.streeviewGroups);
helper.Init(this);
helper.StartDownload();
}
protected void OnDeleteEvent (object sender, DeleteEventArgs a){
Application.Quit();
a.RetVal=true;
}
}
}
And now take a look at the helper code, it downloads data from server but keep the application responsive:
using System;
using System.Collections;
using clientlib;
using widgets;
using Boxerp.Models;
using Boxerp.Objects;
using Gtk;
namespace administrator{
public class MainHelper : ResponsiveHelper{
widgets.SimpleTreeView streeviewEnterprises, streeviewUsers, streeviewGroups;
Enterprise[] enterprises;
User[] users;
Group[] groups;
IAdmin adminObj;
public MainHelper (ref SimpleTreeView e, ref SimpleTreeView u, ref SimpleTreeView g) {
this.streeviewEnterprises=e;
this.streeviewUsers=u;
this.streeviewGroups=g;
adminObj=(IAdmin)RemotingHelper.GetObject(typeof (IAdmin));
}
[Responsive(ResponsiveEnum.Download)]
public void LoadEnterprises (){
try {
enterprises=adminObj.GetEnterprises();
}
catch (Exception ex){
Console.WriteLine(“LoadEnterprise:”+ex.Message);
enterprises=null;
}
}
[Responsive(ResponsiveEnum.Download)]
public void LoadUsers (){
try {
users=adminObj.GetUsers();
}
catch (Exception ex){
users=null;
}
}
…
public override void PopulateGUI (){
InitTreeViews();
if (enterprises!=null)
foreach (Enterprise i in enterprises){
ArrayList columns=new ArrayList();
columns.Add(i.Id.ToString());
columns.Add(i);
columns.Add(i.Description);
this.streeviewEnterprises.InsertRow(TreeIter.Zero, columns);
}
…
Cool!