Saturday, March 3, 2007

Having fun with properties

If you open the View menu in MonoDevelop you'll find listed there two pads which look very similar: "Properties" and "Widget Properties", and you'll also find "Toolbox" and "Widget Palette". The reason for this duplication is that there are two designer models in the IDE: the Stetic model used by the GTK# designer, and the System.Component based model used by the ASP.NET add-in. Today I decided put an end to this duplication, and I started integrating those pads into a single Properties/Toolbox pair.

The System.Component based toolbox is actually not so System.Component dependent. There is a MonoDevelop.DesignerSupport add-in which implements the property and toolbox pads, and which is designed to be pluggable, so I only had extend it from the GTK# designer. After some fixes and improvements I've been able to show the GTK widgets in the toolbox, and to drag&drop them in the designer. It's almost 100% functional now, there are only some small issues to fix, such as the order in which components are shown. But not too much...

Integrating the properties pads has been a bit more tricky. I wanted the properties pad to be very generic and usable not only for visual designers, but also for the IDE in general. So for example if you select a file in the solution pad you would see the properties of the file.

The first problem about the integration is that the Stetic model and the System.Component model are very different. In particular, properties of Stetic components are defined in class descriptors (specified in an xml file), while System.Component model is purely reflection based. Since it's not trivial to implement a property grid which can support both models, the solution has been to completely replace the properties grid depending on what has the focus. When the focus is in the GTK# designer, the properties pad will show the Stetic property grid, and when clicking on the solution pad, it will show the standard System.Component model property grid. We still have two property viewers, but now we have only one properties pad.

The second problem to be solved, is how to detect that the currently selected object has changed, and that the properties pad has to be updated to show the properties of the new selection. In Stetic it is done by tracking focus change events, but it won't work as a generic solution, because the "currently selected object" can be *anything*, not only widgets. For example, the properties pad should change when the selection in the solution tree changes. So I decided to go for a pull model like the one used by the command manager for updating command status. Status of commands is checked periodically by getting the widget that has the focus. If that widget has a handler for the command, it is executed. If not, the command manager looks for a handler in a route of objects which starts on the active widget. This route is by default the chain parents of the widget, but it can be altered. For example, the solution pad re-routes commands to tree extensions before re-routing back to the parent. In this way node extensions have a chance to provide custom behavior for commands.

How is all this related to the properties pad? Well, I'm using the same command target infrastructure to find a potential target object for the properties pad. So, any class in the command route can now not only handle commands, but also provide the "selected object" to be shown in the pad (it only needs to implement the IPropertyPadProvider interface and specifically the GetSelectedComponent() method). I quickly managed to implement a solution pad extension which implements that interface and returns the current tree selection. The result is what you can see in this screenshot:



That is, by selecting any item in the tree, it will show its properties in the properties pad. It still needs a lot of polishing since some properties need to be hidden (it can be done by applying System.ComponentModel attributes), and the properties grid itself is not very stable, but it's looking nice.

4 comments:

Ignacius said...

Hi Lluis!

I was thinking... is it possible to make the toolbox follow the command route so for example there could be one implemented for common comments used on source (think on the GPL header) or such things, show SQL commands when database pad is selected, refactorization commands when class pad selected, etc... Maybe I'm just going crazy because I don't know exactly if the elements on the toolbox must support drag'n drop or they respond to clicked events.

Michael Hutchinson said...

ignacius, the toolbox supports double-click by default, and toolbox consumers can choose to enable drag-n-drop as well. The toolbox tracks the selected document, so it won't be hard to implement source snippets (indeed, that was one of the original design considerations).

Using the toolbox from other pads is an interesting idea, but I don't think it would be very usable in practice.

One thing we can do now is to make it so that the properties pad can be used to edit the toolbox items :)

Daniel Cruz said...

I like this blog is fantastic, is really good written. Congratulation. Do you want to see something more? Read it...: Costa Rica is a country with a extremely sense of freedom. The landscapes are for much the most green in whole center america.The chances of investement are way to high, the average of Americans, European and people of the entire planet who is buying here is up in the sky !!!
Great investment opportunity in Costa Rica: condos, costa rica real estate, costa rica property. Visit us for more info at: http://www.jaco-bay.com/

Kevin said...

牙醫,植牙,矯正,紋身,刺青,創業,批發,皮膚科,痘痘,中醫,飛梭雷射,毛孔粗大,醫學美容,痘痘,肉毒桿菌,seo,關鍵字行銷,關鍵字自然排序,網路行銷,關鍵字自然排序,關鍵字行銷seo,關鍵字廣告,部落格行銷,網路行銷,seo,關鍵字行銷,關鍵字廣告,關鍵字,自然排序,部落格行銷,網路行銷,網路爆紅,牛舌餅婚紗台中婚紗,腳臭,腳臭,腳臭,腳臭,腳臭,腳臭,腳臭,腳臭,中古車,二手車,中古車,二手車,高雄婚紗,街舞,融資,借貸,借錢,小產,雞精,紋身,刺青