Damon Payne: Hand waving software architect

103db signal to noise ratio at < .03% total harmonic distortion
Solution Architect, software developer, geek
Damon Payne at Blogged
2009 Microsoft MVP - Client App Dev
2007 Microsoft MVP - Solution Architecture
 Thursday, December 11, 2008
« Reggie Burnett speaks out on Entity Fram... | Main | Microsoft guy gets an iPhone [0] »

The AGT (Argentum Tela) series of articles is an effort to do two things. Usually an idea is presented only in its finished form. The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches. The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008. This type of application has all sorts of interesting uses. My example is a Home Theater layout tool. Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Yes, I changed the name of the article.  Here at the 19th step, I decided to ditch the old tagline.

Visual and Code Refactoring

After letting Property Editing sit for too long, I have a list of questions to answer and things I've been meaning to fix or refactor.  I publish these Refactoring articles as part of the Reality Blogging commitment but also in case some of the random code is useful to anyone.  Let's get started.

 

Visual Lasso

I don't know why I had a corner radius on the Visual Lasso, I was probably suffering from some Web2.0itus which I am now over.  I change this and changed the colors:

Vision18

The lasso was also crashable by drawing diagonally until the lasso size would involve negative numbers.  This is fixed.

 

Some Questions

I have gotten some questions from interested parties, which I'll answer here.

  • How about a better constructor for LogMessage?
    • Sure.  More constructors provided
  • Where is IDragDropmanager.RemoveDropTarget?
    • Missing.  I can be very focused trying to get these articles out sometimes.  This has been added.
  • In Page.xaml.cs in the example application, why are you resolving IRegionManager when the Page is the IRegionManager implementation?
    • Force of habit, and I was unsure how I was going to leave that.  And there's nothing wrong with talking to yourself using a Contract...
  • Why are the names inconsistent between IPageView and RootPresenter ?
    • Shameful inconsistency.  IPageView has been renamed to IRootView.
  • Why are the names of the Region Controls in Page.xaml not the same as the Regions themselves?
    • More inconsistency.  They are all named XXXRegion now.  As I looked at this I also wondered why I was using Canvas and not a ContentPresenter, possibly something to do with how much ContentPresenter was chaning in Beta2-->RC0.  At any rate, the regions have good names and I've switched to ContentPresenter.
  • In IRegionManager, what is the difference between RootVisual and TopLevelContainer?  Why do you need both of them?
    • RootVisual is meant so that IRegionManager could provide something to System.Windows.Application.RootVisual, and matches its type of UIElement.  I could probably rename this to ApplicationRootVisual since that is the only reason to have this.  TopLevelContainer is used as the main Playground of services that need to do something visually, like DragDropManager.  This isn't as bad as it first seems, for example the built-in "Popup" class must do something very similar.  Comments have been added.

The Border on DesignSite

When is five minus five not zero?  When you have applied a RenderTransform to a FrameworkElement.  For the border on DesignSite, I would move the control by the border thickness (5px) when I would hide or show the border.  Once you have applied a RenderTransform, though, changing a Canvas.XXXProperty by 5px no longer means 5px.  I fixed this by using a transparent and normal border rather than by changing the border thickness from 0 to 5 to show selection.

 

~Creative Commons

Since I had to choose from a list of licenses on Codeplex (I chose MS-PL) I am removing the creative commons snippets from the code as I see them.

 

Clipping

The Canvas does not clip its children.  This means you can drag controls all over the place outside of the Design surface which is obviously undesirable.

Refactor: I extracted a MouseMoveSelection method and made it virtual so the logic was not totally hidden inside an EventHandler.  This method ultimately calls MoveSelection

I needed to make a decision here, to either create a class that extends Canvas or Panel and does perform some form of clipping on its Children, or to simply implement boundaries within the DesignSurface class.  For now I went with enforcing the bounds in code and snapping the selection back to a valid value.

Floating Properties

I went back and finished implementing my original intention for the PropertyGrid, namely that it would float around with the selection and not be statically docked to the right of the surface.

Refactor: I had a TODO item to un-hack the relationship between IDesigner and DesignSite.  Since IDesigner defines a Surface property of type Canvas this was mostly already done.  DesignSite.DesignParent is now of type IDesigner.

Refactor: Some methods, like GetSelectionBounds(), seemed to belong more on IDesigner than DesignSite after the above change was made.

What I sought to do next was pretty vanilla: if IDesignEditorService.Visual currently had a parent, I would remove it from its parent and add it to IDesigner.Surface or IRegionManager.TopLevelContainer in a location close to the right bounds of the current selection.  Control.Parent and VisualTreeHelper.GetParent both have a return type of DependencyObject.  It seems there is no generic way to remove a FrameworkElement from its visual parent.

DamonPayne.AG.IoC.ControlExtensions  now has a RemoveFromParent() extension method.

The PropertyGrid now floats around to be close to the current selection.

Vision19

 

Bigger Surface

In order to set things up for some future articles, I have change the default size of the DesignSurface and the sample application.  Yes, this means it won't fit on a 1024x768 screen, which apparently some people still have even in this late hour.  We'll fix this in a future article but for now I wanted more room to play.

 

A better Toolbox

The way gestures worked in the toolbox had been bothering me, and I thought I could make it better looking anyway, a little more like Visio perhaps.  I nearly introduced an external dependency on the Silverlight Toolkit, but wanted to see how to do this myself instead.  Given the amount of space I'm working with, I needed to add some more furniture.  I have created an area rug, which I feel really ties the room together.

I created a Control extending Panel, WrapLayoutPanel, to property postion them items in my new and improved toolbox.  The MSDN documentation for MeasureOverride and ArrangeOverride was simple, but surprisingly helpful.

Here's the new and improved toolbox:

Vision20

 

  Conclusion

I've finally gotten around to fixing a number of things that have been bothering me, and I think the application looks a little better too.  I am having a hard time deciding what to do next, and I'm afraid the next two installments are not going to be very sexy, but will be very necessary to tie all the concepts together.

The changes in this article are published as version 0.7.18, Codeplex change set 8710.  While things are still very rough, I did go ahead and make this the default public release on Codeplex.

The live demo has been updated at http://www.damonpayne.com/agt