Tuesday, December 27, 2005

I have to say, I'm pretty darned impressed with the way .NET Forms is architected. In stark contrast to MFC or Win32, one can code nearly on intuition. Class names are logical -- Button, TextBox, Label -- and methods are predictable; and once you learn the basics of one widget class (or, more precisely, a widget class and its inheritance chain), things become easy. Very, very easy. Passing instances of managed class pointers around posed no problem; other than declaring the pointer gcroot to embed it in a non-managed class (see details in my previous post).

And best of all, coding the concrete implementations for ButtonImpl, TextImpl, and StaticTextImpl left me with a lot of duplicate, factorable code that I will no doubt be able push up a level to WindowsWidgetImpl, just like I was able to do with Gtk+. All of the controls are positioned, shown, and hidden the same way. Many of the interfaces I am calling against the concrete classes are implemented by the Form's Control class, which Button, Label, and TextBox inherit from, meaning all I should need to do is dynamic_cast my pointers from TextBox, Button, and Label to Control *, and then call a parent class of my design that will handle the actual call into the framework.

One (initially) disappointing cross-platform difference did emerge -- I can't make TextBox controls in .NET so they are not selectable. However, on reflection, that is a minor issue. To be honest, who really would disable the ability to select the text displayed by a text widget, anyway?

I really am very pleased that I was able to get so far so quick. The .NET Framework is really nicely done. My initial impression now is that there is no way I would have gotten as far as I did in the past few hours had I chosen to code against Win32 or MFC, or had the .NET Forms framework been badly designed. Kudos to Microsoft on doing the interfaces right this time.

Here's the complete implementation of WindowsWidgetStaticText:

#include "windowswindowimpl.h"
#include "windowsstatictextimpl.h"

WindowsStaticTextImpl::WindowsStaticTextImpl()
{
}

WindowsStaticTextImpl::~WindowsStaticTextImpl()
{
// destroy the text
}

PRStatus
WindowsStaticTextImpl::Create()
{
m_text = __gc new Label();
if (m_text) {
if (!m_formParent) {
WidgetImpl *top = GetRootWidget();
if (top) {
SetFormParent(top);
}
}

if (m_formParent) {
m_formParent->Controls->Add(m_text);
return PR_SUCCESS;
}
}
return PR_FAILURE;
}

PRStatus
WindowsStaticTextImpl::SetString(const string& value)
{
if (m_text)
m_text->Text = value.c_str();
return PR_SUCCESS;
}

PRStatus
WindowsStaticTextImpl::Show()
{
if (m_text)
m_text->Show();
return ShowImpl();
}

PRStatus
WindowsStaticTextImpl::Hide()
{
if (m_text)
m_text->Hide();
return ShowImpl();
}

PRStatus
WindowsStaticTextImpl::SetGeometry(const int &x, const int &y,
const int &width, const int &height, const char &mask)
{
if (m_text) {
Size size;
Point point;

size = m_text->ClientSize;
point = m_text->Location;

if (mask & GEOM_X)
point.X = x;
if (mask & GEOM_Y)
point.Y = y;
if (mask & GEOM_WIDTH)
size.Width = width;
if (mask & GEOM_HEIGHT)
size.Height = height;

m_text->ClientSize=size;
m_text->Location=point;
}

return PR_SUCCESS;
}

PRStatus
WindowsStaticTextImpl::GetGeometryRequest(int &x, int &y, int &width,
int &height)
{
Size size, request(0, 0);

if (m_text) {
size = m_text->ClientSize;
width = size.get_Width();
height = m_text->PreferredHeight;
}
return PR_SUCCESS;
}

And, here's the screenshot I promised (but didn't expect to see so soon):



Next steps: handle resizing (I need to learn how to handle window resize events in .NET) and button presses (ditto for the learning curve), plus a bit of work to wire up the components, using the abstract mechanisms already being used by the Cocoa and Gtk+ implementations. So, I'm not completely done. But, as you can see, a lot has been accomplished in about 4 or 5 hours of work!

0 Comments:

Post a Comment

<< Home