Today I had lunch with the man that Bill Gates bought Word from.
And I got fired.
What a day.
Wednesday, December 19, 2007
Monday, November 26, 2007
The other 40%
It seems Jeff Atwood's post on the Two Types of Programmers, as well is it's mother post, has missed a very important niche in the development community: The Microsoft Fanboys.
These are the ones that jumped at the opportunity to develop with MONO, and competed in the Code Project's Race to Linux. The developers who read the C# 3.0 Language Specification just ot improve the CLS compliance of their code. The developers who where hired on to those measly "internal" jobs with the sole purpose of upgrading the companies legacy code to .NET, and convince the company they need MSDN just so they can come home at night and install nightly builds of Windows Server, SQL Server, and Visual Studio in hopes of keeping that company ahead of the curve.
The detail that both Jeff and Ben leave out is the propensity of many Microsoft developers to be just as passionate and dedicated as any Open Source dev.
I have an immense amount of respect for anyone who calls themselves "Open Source" and yet does their best to evangelize a Microsoft product. I think it is especially a great testament to what Microsoft has created in .NET when open source advocates like Jeff actually call for more open source .NET projects like MONO and others.
I just think it's a sad reality that many of the best software out there is kept behind closed doors for this same reason. The sad facts are stated clearly above. The open source guys can get their companies to use any open source tools, so the best open source doesn't make it into the enterprise, while the fanboys are constantly innovating in the enterprise, but are bound by law in some cases to keep their technology proprietary.
It's a simple but sad state of affairs that in my own cynical mind has no hope of changing any time soon.
These are the ones that jumped at the opportunity to develop with MONO, and competed in the Code Project's Race to Linux. The developers who read the C# 3.0 Language Specification just ot improve the CLS compliance of their code. The developers who where hired on to those measly "internal" jobs with the sole purpose of upgrading the companies legacy code to .NET, and convince the company they need MSDN just so they can come home at night and install nightly builds of Windows Server, SQL Server, and Visual Studio in hopes of keeping that company ahead of the curve.
The detail that both Jeff and Ben leave out is the propensity of many Microsoft developers to be just as passionate and dedicated as any Open Source dev.
Shocking Comment #1: I like programming and really enjoy ASP.NET. I think it's neat and fun and interesting and cool how you can go from literally nothing to having a data-driven web application that can be used by people around the world in an amazingly fast amount of time. Furthermore, I want to spread that enthusiasm to folks.
I have an immense amount of respect for anyone who calls themselves "Open Source" and yet does their best to evangelize a Microsoft product. I think it is especially a great testament to what Microsoft has created in .NET when open source advocates like Jeff actually call for more open source .NET projects like MONO and others.
Shocking Comment #2: [The alpha-geeks] get all excited about the latest Linux distro or AJAX toolkit or distributed SCM system, spend all weekend on it, blog about it… and then are confounded about why they can’t get their office to start using it.
I just think it's a sad reality that many of the best software out there is kept behind closed doors for this same reason. The sad facts are stated clearly above. The open source guys can get their companies to use any open source tools, so the best open source doesn't make it into the enterprise, while the fanboys are constantly innovating in the enterprise, but are bound by law in some cases to keep their technology proprietary.
It's a simple but sad state of affairs that in my own cynical mind has no hope of changing any time soon.
Wednesday, October 31, 2007
VB. It's good for something...
For better or worse, I spend a lot of time trying to explain real life situations in code.
Below is the thought process of Paul McCartney when writing "Let it Be".
Public Class Beatles
Private hardship As New Death(Of Mother)
Protected help As Mother
Private WithEvents life As New Paul()
Public Sub New()
If help Is Nothing Then
life.Experiece(hardship)
life.Experiece(New Hour(Of Darkness))
End If
End Sub
Public Sub Sing() Handles life.TimeExperienced
While life.Contains(hardship)
Me.help = hardship.Help
Whisper.Words(Of Wisdom)(help)
life.RecoverFrom(hardship)
End While
End Sub
End Class
Class Trouble
End Class
Class Death(Of T)
Inherits Time(Of Trouble)
End Class
Class Time(Of T)
Private _help As Mother = New Mary()
Public Property Help() As Mother
Get
Return _help
End Get
Set(ByVal value As Mother)
_help = value
End Set
End Property
End Class
Class Hardship
Inherits Time(Of Trouble)
Public ReadOnly Property Cause() As Time(Of Trouble)
Get
Return New Darkness()
End Get
End Property
End Class
Class Darkness
Inherits Time(Of Trouble)
End Class
Class Hour(Of T As Time(Of Trouble))
Inherits Time(Of Trouble)
End Class
Class Times(Of T)
Inherits List(Of Time(Of T))
End Class
Class Life(Of T)
Private times As New Times(Of T)
Function Contains(ByVal time As Time(Of T)) As Boolean
Return times.Contains(time)
End Function
Sub Experiece(ByVal time As Time(Of T))
times.Add(time)
RaiseEvent TimeExperienced()
End Sub
Sub RecoverFrom(ByVal time As Time(Of T))
times.Remove(time)
End Sub
Default Public ReadOnly Property Time(ByVal index As Integer) As Time(Of T)
Get
Return times(index)
End Get
End Property
Public Event TimeExperienced()
End Class
Class Paul
Inherits Life(Of Trouble)
End Class
Public Class Whisper
Shared Sub Words(Of T)(ByVal m As Mother)
Console.WriteLine(m.Advice)
End Sub
End Class
Public Class Mother
Private _advice As String
Public Property Advice() As String
Get
Return _advice
End Get
Set(ByVal value As String)
_advice = value
End Set
End Property
End Class
Class Mary
Inherits Mother
Public Sub New()
Advice = "let it be"
End Sub
Public Overrides Function ToString() As String
Return Advice
End Function
End Class
Public Class Wisdom
Inherits Knowledge
End Class
Public Class Knowledge
End Class
Public Class Hit
Public Shared Sub Create()
Dim b As New Beatles
End Sub
End Class
Below is the thought process of Paul McCartney when writing "Let it Be".
Public Class Beatles
Private hardship As New Death(Of Mother)
Protected help As Mother
Private WithEvents life As New Paul()
Public Sub New()
If help Is Nothing Then
life.Experiece(hardship)
life.Experiece(New Hour(Of Darkness))
End If
End Sub
Public Sub Sing() Handles life.TimeExperienced
While life.Contains(hardship)
Me.help = hardship.Help
Whisper.Words(Of Wisdom)(help)
life.RecoverFrom(hardship)
End While
End Sub
End Class
Class Trouble
End Class
Class Death(Of T)
Inherits Time(Of Trouble)
End Class
Class Time(Of T)
Private _help As Mother = New Mary()
Public Property Help() As Mother
Get
Return _help
End Get
Set(ByVal value As Mother)
_help = value
End Set
End Property
End Class
Class Hardship
Inherits Time(Of Trouble)
Public ReadOnly Property Cause() As Time(Of Trouble)
Get
Return New Darkness()
End Get
End Property
End Class
Class Darkness
Inherits Time(Of Trouble)
End Class
Class Hour(Of T As Time(Of Trouble))
Inherits Time(Of Trouble)
End Class
Class Times(Of T)
Inherits List(Of Time(Of T))
End Class
Class Life(Of T)
Private times As New Times(Of T)
Function Contains(ByVal time As Time(Of T)) As Boolean
Return times.Contains(time)
End Function
Sub Experiece(ByVal time As Time(Of T))
times.Add(time)
RaiseEvent TimeExperienced()
End Sub
Sub RecoverFrom(ByVal time As Time(Of T))
times.Remove(time)
End Sub
Default Public ReadOnly Property Time(ByVal index As Integer) As Time(Of T)
Get
Return times(index)
End Get
End Property
Public Event TimeExperienced()
End Class
Class Paul
Inherits Life(Of Trouble)
End Class
Public Class Whisper
Shared Sub Words(Of T)(ByVal m As Mother)
Console.WriteLine(m.Advice)
End Sub
End Class
Public Class Mother
Private _advice As String
Public Property Advice() As String
Get
Return _advice
End Get
Set(ByVal value As String)
_advice = value
End Set
End Property
End Class
Class Mary
Inherits Mother
Public Sub New()
Advice = "let it be"
End Sub
Public Overrides Function ToString() As String
Return Advice
End Function
End Class
Public Class Wisdom
Inherits Knowledge
End Class
Public Class Knowledge
End Class
Public Class Hit
Public Shared Sub Create()
Dim b As New Beatles
End Sub
End Class
Thursday, October 25, 2007
Wanted:
Programmer.
Must work be able to work unreasonable amounts of time, on impossible deadlines, with insufficient resources, inadequate compensation, conflicting orders, and be have ability to read boss's mind and accept responsibility for everything that goes wrong.
Must work be able to work unreasonable amounts of time, on impossible deadlines, with insufficient resources, inadequate compensation, conflicting orders, and be have ability to read boss's mind and accept responsibility for everything that goes wrong.
Wednesday, October 3, 2007
Finally! Someone with a brain!
This post should be put on a pedestal and bowed down to by millions.
I think every developer on the planet that has had to dip into legacy code has been in the same situation as I was a month ago: "It's my fault that the stored proc sent out 15,000 of the same email? How was i supposed to know it was in a while loop? The loop itself was nested 300 lines deep with 300 lines within it! It took 10 seconds of scrolling to get from the declaration to the end!"
I think every developer on the planet that has had to dip into legacy code has been in the same situation as I was a month ago: "It's my fault that the stored proc sent out 15,000 of the same email? How was i supposed to know it was in a while loop? The loop itself was nested 300 lines deep with 300 lines within it! It took 10 seconds of scrolling to get from the declaration to the end!"
Monday, October 1, 2007
An Eternal Paradox
/*
* Why the Internet cannot stop making references to MC Hammer.
*/
namespace Paradox
{
using System;
using The90s;
static class Program
{
static void Main()
{
Hit og = Hit.Create();
Console.WriteLine(og.StillCool.ToString()); // PM NOTE: fails unit tests.
Hit meme = new Hit(true);
Console..WriteLine(meme.StillCool.ToString()); / PM NOTE: fails unit tests.
}
}
namespace The90s
{
public class Hit
{
bool _stillCool = false;
public Hit(bool stopUse)
{
_stillCool = stopUse;
}
static bool Stop()
{
return false;
}
static bool Collaborate()
{
return false;
}
static bool Listen()
{
return false;
}
public static Hit Create()
{
if (Stop())
return new Hit(Collaborate() && Listen());
else return new Hit(true);
}
public bool StillCool
{
get { return _stillCool; }
}
}
}
}
* Why the Internet cannot stop making references to MC Hammer.
*/
namespace Paradox
{
using System;
using The90s;
static class Program
{
static void Main()
{
Hit og = Hit.Create();
Console.WriteLine(og.StillCool.ToString()); // PM NOTE: fails unit tests.
Hit meme = new Hit(true);
Console..WriteLine(meme.StillCool.ToString()); / PM NOTE: fails unit tests.
}
}
namespace The90s
{
public class Hit
{
bool _stillCool = false;
public Hit(bool stopUse)
{
_stillCool = stopUse;
}
static bool Stop()
{
return false;
}
static bool Collaborate()
{
return false;
}
static bool Listen()
{
return false;
}
public static Hit Create()
{
if (Stop())
return new Hit(Collaborate() && Listen());
else return new Hit(true);
}
public bool StillCool
{
get { return _stillCool; }
}
}
}
}
Thursday, September 27, 2007
Predilection to (lack of) Implementation
I find it strange, as an enterprise software developer, that I can write 1000+ lines of code on a whim--without so much as building the application once. It's not that I have any particular level of trust in the fact that my code will work, it's just that... Well, here's an example:
All of the above code was done with no building to check syntax, and no form to associate it with.
Funny thing is, when I did build it--and after more than a few bug fixes--I did decide to try it out, and guess what I couldn't figure out? How to get my control to follow the cursor without if flickering all over the place.
What this has taught me is that, despite my slogan (see this blog's subtitle), sometimes a team is just best. Maybe even a team of two, but a team nonetheless. Problem is, this environment I work in isn't exactly conducive to "team-based" development. For the past 20 years this company has had between 2 and 20 developers at any given time, and not once did any of those developers collaborate on a single application, practice, or methodology. This is why I've made it my goal to spend the next few months working my way up the manufacturing line re-writing every application in use, all the while building a framework that, if I can pitch it well enough to the powers that be, will be used for all future application development in this company. (Or at least this division, anyway.)
Now again, I won't even pretend that anything I develop here is "production-quality"--my base data access classes don't even support Transactions (laziness...)--but my goal isn't to get my code out on the floor, it's nothing more than to enforce some good architecture. Any good enterprise developer will tell you that 300 applications, all with their own data access layers is a date with disaster, and this fact has been proven many times over in our company. Problem is, no one, and I mean no one, not the developers, not the management, not even the new head of the development department has a clue what the phrase "software architecture" means in a broad sense.
I blame this ignorance mostly on their experience. the VB6 standard libraries are hardly the most robust things on the planet, it's probably 30Mb total of compile code. Now 175Mb for .NET 2.0 isn't huge, but the tools provided with it and the architecture of the framework itself does more than demonstrate how things should be organized in a production-quality system. Now of course I don't mean to imply that VB6 isn't enterprise ready, after all, many of the largest businesses in the country either have before or still today run entirely on VB6-based systems; I can't help thinking though of what could have come of those very same organizations had something like ASP.NET, Ruby on Rails, or the concept of "AJAX" had been around back during the original .com bubble.
Or what kind of "production-quality" code could be running this company if I weren't so confused as to why my controls aren't gaining focus when I click them...
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System.Windows.Forms;
namespace Precision.Design
{
#region Enums & Stuff
enum ResizeHandlePosition
{
TopLeft = 0,
TopRight = 1,
BottomLeft = 2,
BottomRight = 3,
Top = 4,
Bottom = 5,
Left = 6,
Right = 7
}
#endregion
public class DesignerControl : UserControl
{
#region Fields
private static readonly int DefaultWidth = 100;
private static readonly int DefaultHeight = 100;
private const int BorderWidth = 6;
private const int BorderHeight = 6;
private const int HandleCount = 4;
private Rectangle[] handles = new Rectangle[HandleCount];
private static readonly int HandleWidth = 5;
private static readonly int HandleHeight = 5;
private static readonly Size HandleSize = new Size(HandleWidth, HandleHeight);
private Pen borderPen = new Pen(Color.Black, 1);
private Pen handlePen = new Pen(Color.Black, 1);
private const int borderOffset = BorderWidth - 4;
private static Rectangle _borderRect = new Rectangle(borderOffset, borderOffset, DefaultWidth - borderOffset, DefaultHeight - borderOffset);
#endregion
public DesignerControl()
{
borderPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
for (int i = 0; i < size =" HandleSize;" backcolor =" System.Drawing.Color.Transparent;" brush =" Brushes.Transparent;" brush =" Brushes.Transparent;" brush =" Brushes.Black;" brush =" Brushes.Black;" i =" 0;" maxx =" BorderWidth" maxy =" BorderWidth" maxwidth =" this.Width" maxheight =" this.Height" left =" e.Control.Left" top =" e.Control.Top" left =" e.Control.Left"> maxX ? maxX : e.Control.Left;
e.Control.Top = e.Control.Top > maxY ? maxY : e.Control.Top;
e.Control.Width = e.Control.Width > maxWidth ? maxWidth : e.Control.Width;
e.Control.Height = e.Control.Height > maxHeight ? maxHeight : e.Control.Height;
base.OnControlAdded(e);
}
protected override void OnResize(EventArgs e)
{
_borderRect.Width = this.Width - BorderWidth;
_borderRect.Height = this.Height - BorderWidth;
handles[ResizeHandlePosition.TopLeft].Location = new Point(0, 0);
handles[ResizeHandlePosition.TopRight].Location = new Point(this.Width - HandleWidth - borderOffset, this.Top);
handles[ResizeHandlePosition.BottomLeft].Location = new Point(0, this.Bottom - HandleHeight - borderOffset);
handles[ResizeHandlePosition.BottomRight].Location = new Point(this.Width - HandleWidth - borderOffset, this.Bottom - HandleHeight - borderOffset);
base.OnResize(e);
}
#endregion
#region Mouse Stuff
protected override void OnMouseHover(EventArgs e)
{
if (!this.ContainsFocus) return;
Point curPos = PointToClient(Cursor.Position);
if (handles[0].Contains(curPos))
{
Cursor = Cursors.SizeNWSE;
}
else if (handles[1].Contains(curPos))
{
Cursor = Cursors.SizeNESW;
}
else if (handles[2].Contains(curPos))
{
Cursor = Cursors.SizeNWSE;
}
else if (handles[3].Contains(curPos))
{
Cursor = Cursors.SizeNESW;
}
else
{
Cursor = Cursors.SizeAll;
}
base.OnMouseHover(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
}
protected override void OnGotFocus(EventArgs e)
{
if (!this.ContainsFocus) return;
Cursor = Cursors.SizeAll;
base.OnGotFocus(e);
}
#endregion
}
}
namespace Precision.Design
{
public partial class AssemblyDesignerControl : UserControl
{
public AssemblyDesignerControl()
{
InitializeComponent();
TextView.Dispose();
}
public void AddControl(string name, Point loc)
{ AddControl(name, loc.X, loc.Y); }
public void AddControl(string name, int x, int y)
{ DesignSurface.AddControl(name, x, y); }
}
}
namespace Precision.Design.Controls
{
public class Label : System.Windows.Forms.Label
{
System.Windows.Forms.Label _label = new System.Windows.Forms.Label();
public Label(string text)
{
_label.Text = text;
_label.Height = 200;
_label.Width = 200;
_label.BackColor = SystemColors.Control;
_label.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
_label.Click += new EventHandler(_label_Click);
this.Controls.Add(_label);
}
void _label_Click(object sender, EventArgs e)
{
this.Focus();
}
protected override void OnGotFocus(EventArgs e)
{
_label.Focus();
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (!ContainsFocus) return;
if (e.Button == MouseButtons.Left)
this.Location = Cursor.Position;
base.OnMouseMove(e);
}
private NotifiedForm _parent;
public new NotifiedForm Parent
{
get { return _parent; }
set { _parent = value; }
}
}
}
using System;
using System.Drawing;
using Winforms = System.Windows.Forms;
using Precision.Design;
using Precision.Design.Controls;
/* TODO:
* 1. Double-Buffering
* 2. Export to bitmap
* 3. ???
* 4. Profit!
*/
namespace Precision.Design
{
internal class AssemblyDesignSurface : Winforms.Panel
{
private new static readonly Color DefaultBackColor = SystemColors.Window;
//private static Graphics _backbuffer;
public AssemblyDesignSurface()
:base()
{
this.AllowDrop = true;
this.BackColor = DefaultBackColor;
this.AutoScroll = true;
}
protected override void OnDragDrop(Winforms.DragEventArgs e)
{
if (e.Data.GetDataPresent(Winforms.DataFormats.StringFormat))
{
AddControl(
(string)e.Data.GetData(Winforms.DataFormats.StringFormat),
this.PointToClient(new Point(e.X, e.Y))
);
}
base.OnDragDrop(e);
}
protected override void OnDragEnter(Winforms.DragEventArgs e)
{
base.OnDragEnter(e);
}
protected override void OnDragOver(Winforms.DragEventArgs e)
{
if (!e.Data.GetDataPresent(Winforms.DataFormats.StringFormat))
e.Effect = System.Windows.Forms.DragDropEffects.None;
else
e.Effect = System.Windows.Forms.DragDropEffects.Copy;
base.OnDragOver(e);
}
protected override void OnDragLeave(EventArgs e)
{
base.OnDragLeave(e);
}
protected override void OnQueryContinueDrag(Winforms.QueryContinueDragEventArgs e)
{
base.OnQueryContinueDrag(e);
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
//_backbuffer = e.Graphics;
base.OnPaint(e);
}
public void AddControl(string name, Point loc)
{ AddControl(name, loc.X, loc.Y); }
public void AddControl(string name, int x, int y)
{
if (name == "Label")
{
Label lbl = new Label("Label1");
lbl.Location = new Point(x, y);
Controls.Add(lbl);
//ControlResizer rzr = new ControlResizer(lbl);
lbl.Focus();
}
else if (name == "TextBox")
{
}
else if (name == "Background")
{
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
namespace Precision.Design
{
public class AssemblyToolBox : ListBox
{
private new static readonly Color DefaultBackColor = SystemColors.Control;
private static readonly string DefaultText = string.Empty;
private ToolBoxItemCollection _items = new ToolBoxItemCollection();
public AssemblyToolBox()
: this(null) { }
public AssemblyToolBox(IEnumerable items)
{
this.Text = DefaultText;
if (items != null) _items = new ToolBoxItemCollection(items);
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (Items.Count == 0) return;
int index = IndexFromPoint(e.X, e.Y);
DragDropEffects effect = DoDragDrop(Items[index].ToString(), DragDropEffects.Copy | DragDropEffects.Scroll);
}
protected override void OnQueryContinueDrag(QueryContinueDragEventArgs qcdevent)
{
base.OnQueryContinueDrag(qcdevent);
}
}
#region Item Collection
public class ToolBoxItemCollection : IEnumerable, IList
{
private List _items = new List();
public ToolBoxItemCollection()
: this(null) { }
public ToolBoxItemCollection(IEnumerable items)
{
if (items != null) _items = new List(items);
}
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
#endregion
#region IList Members
public void Add(ToolBoxItem item)
{
if (!_items.Contains(item))
_items.Add(item);
else throw new InvalidOperationException("Cannot add duplicate item to list");
}
public void Remove(ToolBoxItem item)
{
_items.Remove(item);
}
public int IndexOf(ToolBoxItem item)
{
return _items.IndexOf(item);
}
public void Insert(int index, ToolBoxItem item)
{
_items.Insert(index, item);
}
public void RemoveAt(int index)
{
_items.RemoveAt(index);
}
public ToolBoxItem this[int index]
{
get
{
return _items[index];
}
set
{
_items[index] = value;
}
}
#endregion
#region ICollection Members
public void Clear()
{
_items.Clear();
}
public bool Contains(ToolBoxItem item)
{
return _items.Contains(item);
}
public void CopyTo(ToolBoxItem[] array, int arrayIndex)
{
_items.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
bool ICollection.Remove(ToolBoxItem item)
{
return _items.Remove(item);
}
#endregion
}
#endregion
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
namespace Precision.Design
{
public class EditableControl : DesignerControl
{
private static readonly BufferedGraphics NO_MANAGED_BACK_BUFFER = null;
private static readonly Brush DefaultBrush = Brushes.Black;
BufferedGraphicsContext GraphicsManager;
BufferedGraphics BackBuffer;
private bool _selected;
public EditableControl()
{
this.Height = 100;
this.Width = 100;
SetUpDoubleBuffer();
Invalidate();
}
#region Painting Stuff
private void SetUpDoubleBuffer()
{
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
GraphicsManager = BufferedGraphicsManager.Current;
GraphicsManager.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
BackBuffer = GraphicsManager.Allocate(this.CreateGraphics(), ClientRectangle);
}
protected override void OnResize(EventArgs e)
{
//if (BackBuffer != NO_MANAGED_BACK_BUFFER)
// BackBuffer.Dispose();
//GraphicsManager.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
//BackBuffer = GraphicsManager.Allocate(this.CreateGraphics(), ClientRectangle);
//this.Refresh();
base.OnResize(e);
}
protected override void OnPaint(PaintEventArgs e)
{
// TODO: Turn on when fixed.
//BackBuffer.Render(e.Graphics);
base.OnPaint(e);
}
#endregion
#region Moving and Focus
protected override void OnMove(EventArgs e)
{
base.OnMove(e);
}
protected override void OnGotFocus(EventArgs e)
{
_selected = true;
Invalidate();
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
_selected = false;
base.OnLostFocus(e);
}
protected override void OnMouseClick(MouseEventArgs e)
{
OnGotFocus(e);
base.OnMouseClick(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
//_selected = true;
////Point pt = Cursor.Position;
//offset = e.Location;
//_beginPoint = new Point(e.X + this.Left, e.Y + this.Top);
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int x = Cursor.Position.X - 350;
int y = Cursor.Position.Y - 350;
this.Left = x < top =" y" location =" Cursor.Position;" _selected =" false;" pt =" Cursor.Position;" _endpoint =" new" _selected =" value;" _selected =" selected;" _selected =" value;">
(For those of you who are curious, this will probably build, but it won't do much)using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System.Windows.Forms;
namespace Precision.Design
{
#region Enums & Stuff
enum ResizeHandlePosition
{
TopLeft = 0,
TopRight = 1,
BottomLeft = 2,
BottomRight = 3,
Top = 4,
Bottom = 5,
Left = 6,
Right = 7
}
#endregion
public class DesignerControl : UserControl
{
#region Fields
private static readonly int DefaultWidth = 100;
private static readonly int DefaultHeight = 100;
private const int BorderWidth = 6;
private const int BorderHeight = 6;
private const int HandleCount = 4;
private Rectangle[] handles = new Rectangle[HandleCount];
private static readonly int HandleWidth = 5;
private static readonly int HandleHeight = 5;
private static readonly Size HandleSize = new Size(HandleWidth, HandleHeight);
private Pen borderPen = new Pen(Color.Black, 1);
private Pen handlePen = new Pen(Color.Black, 1);
private const int borderOffset = BorderWidth - 4;
private static Rectangle _borderRect = new Rectangle(borderOffset, borderOffset, DefaultWidth - borderOffset, DefaultHeight - borderOffset);
#endregion
public DesignerControl()
{
borderPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
for (int i = 0; i < size =" HandleSize;" backcolor =" System.Drawing.Color.Transparent;" brush =" Brushes.Transparent;" brush =" Brushes.Transparent;" brush =" Brushes.Black;" brush =" Brushes.Black;" i =" 0;" maxx =" BorderWidth" maxy =" BorderWidth" maxwidth =" this.Width" maxheight =" this.Height" left =" e.Control.Left" top =" e.Control.Top" left =" e.Control.Left"> maxX ? maxX : e.Control.Left;
e.Control.Top = e.Control.Top > maxY ? maxY : e.Control.Top;
e.Control.Width = e.Control.Width > maxWidth ? maxWidth : e.Control.Width;
e.Control.Height = e.Control.Height > maxHeight ? maxHeight : e.Control.Height;
base.OnControlAdded(e);
}
protected override void OnResize(EventArgs e)
{
_borderRect.Width = this.Width - BorderWidth;
_borderRect.Height = this.Height - BorderWidth;
handles[ResizeHandlePosition.TopLeft].Location = new Point(0, 0);
handles[ResizeHandlePosition.TopRight].Location = new Point(this.Width - HandleWidth - borderOffset, this.Top);
handles[ResizeHandlePosition.BottomLeft].Location = new Point(0, this.Bottom - HandleHeight - borderOffset);
handles[ResizeHandlePosition.BottomRight].Location = new Point(this.Width - HandleWidth - borderOffset, this.Bottom - HandleHeight - borderOffset);
base.OnResize(e);
}
#endregion
#region Mouse Stuff
protected override void OnMouseHover(EventArgs e)
{
if (!this.ContainsFocus) return;
Point curPos = PointToClient(Cursor.Position);
if (handles[0].Contains(curPos))
{
Cursor = Cursors.SizeNWSE;
}
else if (handles[1].Contains(curPos))
{
Cursor = Cursors.SizeNESW;
}
else if (handles[2].Contains(curPos))
{
Cursor = Cursors.SizeNWSE;
}
else if (handles[3].Contains(curPos))
{
Cursor = Cursors.SizeNESW;
}
else
{
Cursor = Cursors.SizeAll;
}
base.OnMouseHover(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
}
protected override void OnGotFocus(EventArgs e)
{
if (!this.ContainsFocus) return;
Cursor = Cursors.SizeAll;
base.OnGotFocus(e);
}
#endregion
}
}
namespace Precision.Design
{
public partial class AssemblyDesignerControl : UserControl
{
public AssemblyDesignerControl()
{
InitializeComponent();
TextView.Dispose();
}
public void AddControl(string name, Point loc)
{ AddControl(name, loc.X, loc.Y); }
public void AddControl(string name, int x, int y)
{ DesignSurface.AddControl(name, x, y); }
}
}
namespace Precision.Design.Controls
{
public class Label : System.Windows.Forms.Label
{
System.Windows.Forms.Label _label = new System.Windows.Forms.Label();
public Label(string text)
{
_label.Text = text;
_label.Height = 200;
_label.Width = 200;
_label.BackColor = SystemColors.Control;
_label.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
_label.Click += new EventHandler(_label_Click);
this.Controls.Add(_label);
}
void _label_Click(object sender, EventArgs e)
{
this.Focus();
}
protected override void OnGotFocus(EventArgs e)
{
_label.Focus();
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (!ContainsFocus) return;
if (e.Button == MouseButtons.Left)
this.Location = Cursor.Position;
base.OnMouseMove(e);
}
private NotifiedForm _parent;
public new NotifiedForm Parent
{
get { return _parent; }
set { _parent = value; }
}
}
}
using System;
using System.Drawing;
using Winforms = System.Windows.Forms;
using Precision.Design;
using Precision.Design.Controls;
/* TODO:
* 1. Double-Buffering
* 2. Export to bitmap
* 3. ???
* 4. Profit!
*/
namespace Precision.Design
{
internal class AssemblyDesignSurface : Winforms.Panel
{
private new static readonly Color DefaultBackColor = SystemColors.Window;
//private static Graphics _backbuffer;
public AssemblyDesignSurface()
:base()
{
this.AllowDrop = true;
this.BackColor = DefaultBackColor;
this.AutoScroll = true;
}
protected override void OnDragDrop(Winforms.DragEventArgs e)
{
if (e.Data.GetDataPresent(Winforms.DataFormats.StringFormat))
{
AddControl(
(string)e.Data.GetData(Winforms.DataFormats.StringFormat),
this.PointToClient(new Point(e.X, e.Y))
);
}
base.OnDragDrop(e);
}
protected override void OnDragEnter(Winforms.DragEventArgs e)
{
base.OnDragEnter(e);
}
protected override void OnDragOver(Winforms.DragEventArgs e)
{
if (!e.Data.GetDataPresent(Winforms.DataFormats.StringFormat))
e.Effect = System.Windows.Forms.DragDropEffects.None;
else
e.Effect = System.Windows.Forms.DragDropEffects.Copy;
base.OnDragOver(e);
}
protected override void OnDragLeave(EventArgs e)
{
base.OnDragLeave(e);
}
protected override void OnQueryContinueDrag(Winforms.QueryContinueDragEventArgs e)
{
base.OnQueryContinueDrag(e);
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
//_backbuffer = e.Graphics;
base.OnPaint(e);
}
public void AddControl(string name, Point loc)
{ AddControl(name, loc.X, loc.Y); }
public void AddControl(string name, int x, int y)
{
if (name == "Label")
{
Label lbl = new Label("Label1");
lbl.Location = new Point(x, y);
Controls.Add(lbl);
//ControlResizer rzr = new ControlResizer(lbl);
lbl.Focus();
}
else if (name == "TextBox")
{
}
else if (name == "Background")
{
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
namespace Precision.Design
{
public class AssemblyToolBox : ListBox
{
private new static readonly Color DefaultBackColor = SystemColors.Control;
private static readonly string DefaultText = string.Empty;
private ToolBoxItemCollection _items = new ToolBoxItemCollection();
public AssemblyToolBox()
: this(null) { }
public AssemblyToolBox(IEnumerable
{
this.Text = DefaultText;
if (items != null) _items = new ToolBoxItemCollection(items);
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (Items.Count == 0) return;
int index = IndexFromPoint(e.X, e.Y);
DragDropEffects effect = DoDragDrop(Items[index].ToString(), DragDropEffects.Copy | DragDropEffects.Scroll);
}
protected override void OnQueryContinueDrag(QueryContinueDragEventArgs qcdevent)
{
base.OnQueryContinueDrag(qcdevent);
}
}
#region Item Collection
public class ToolBoxItemCollection : IEnumerable
{
private List
public ToolBoxItemCollection()
: this(null) { }
public ToolBoxItemCollection(IEnumerable
{
if (items != null) _items = new List
}
#region IEnumerable
public IEnumerator
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
#endregion
#region IList
public void Add(ToolBoxItem item)
{
if (!_items.Contains(item))
_items.Add(item);
else throw new InvalidOperationException("Cannot add duplicate item to list");
}
public void Remove(ToolBoxItem item)
{
_items.Remove(item);
}
public int IndexOf(ToolBoxItem item)
{
return _items.IndexOf(item);
}
public void Insert(int index, ToolBoxItem item)
{
_items.Insert(index, item);
}
public void RemoveAt(int index)
{
_items.RemoveAt(index);
}
public ToolBoxItem this[int index]
{
get
{
return _items[index];
}
set
{
_items[index] = value;
}
}
#endregion
#region ICollection
public void Clear()
{
_items.Clear();
}
public bool Contains(ToolBoxItem item)
{
return _items.Contains(item);
}
public void CopyTo(ToolBoxItem[] array, int arrayIndex)
{
_items.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
bool ICollection
{
return _items.Remove(item);
}
#endregion
}
#endregion
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
namespace Precision.Design
{
public class EditableControl : DesignerControl
{
private static readonly BufferedGraphics NO_MANAGED_BACK_BUFFER = null;
private static readonly Brush DefaultBrush = Brushes.Black;
BufferedGraphicsContext GraphicsManager;
BufferedGraphics BackBuffer;
private bool _selected;
public EditableControl()
{
this.Height = 100;
this.Width = 100;
SetUpDoubleBuffer();
Invalidate();
}
#region Painting Stuff
private void SetUpDoubleBuffer()
{
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
GraphicsManager = BufferedGraphicsManager.Current;
GraphicsManager.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
BackBuffer = GraphicsManager.Allocate(this.CreateGraphics(), ClientRectangle);
}
protected override void OnResize(EventArgs e)
{
//if (BackBuffer != NO_MANAGED_BACK_BUFFER)
// BackBuffer.Dispose();
//GraphicsManager.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
//BackBuffer = GraphicsManager.Allocate(this.CreateGraphics(), ClientRectangle);
//this.Refresh();
base.OnResize(e);
}
protected override void OnPaint(PaintEventArgs e)
{
// TODO: Turn on when fixed.
//BackBuffer.Render(e.Graphics);
base.OnPaint(e);
}
#endregion
#region Moving and Focus
protected override void OnMove(EventArgs e)
{
base.OnMove(e);
}
protected override void OnGotFocus(EventArgs e)
{
_selected = true;
Invalidate();
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
_selected = false;
base.OnLostFocus(e);
}
protected override void OnMouseClick(MouseEventArgs e)
{
OnGotFocus(e);
base.OnMouseClick(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
//_selected = true;
////Point pt = Cursor.Position;
//offset = e.Location;
//_beginPoint = new Point(e.X + this.Left, e.Y + this.Top);
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int x = Cursor.Position.X - 350;
int y = Cursor.Position.Y - 350;
this.Left = x < top =" y" location =" Cursor.Position;" _selected =" false;" pt =" Cursor.Position;" _endpoint =" new" _selected =" value;" _selected =" selected;" _selected =" value;">
All of the above code was done with no building to check syntax, and no form to associate it with.
Funny thing is, when I did build it--and after more than a few bug fixes--I did decide to try it out, and guess what I couldn't figure out? How to get my control to follow the cursor without if flickering all over the place.
What this has taught me is that, despite my slogan (see this blog's subtitle), sometimes a team is just best. Maybe even a team of two, but a team nonetheless. Problem is, this environment I work in isn't exactly conducive to "team-based" development. For the past 20 years this company has had between 2 and 20 developers at any given time, and not once did any of those developers collaborate on a single application, practice, or methodology. This is why I've made it my goal to spend the next few months working my way up the manufacturing line re-writing every application in use, all the while building a framework that, if I can pitch it well enough to the powers that be, will be used for all future application development in this company. (Or at least this division, anyway.)
Now again, I won't even pretend that anything I develop here is "production-quality"--my base data access classes don't even support Transactions (laziness...)--but my goal isn't to get my code out on the floor, it's nothing more than to enforce some good architecture. Any good enterprise developer will tell you that 300 applications, all with their own data access layers is a date with disaster, and this fact has been proven many times over in our company. Problem is, no one, and I mean no one, not the developers, not the management, not even the new head of the development department has a clue what the phrase "software architecture" means in a broad sense.
I blame this ignorance mostly on their experience. the VB6 standard libraries are hardly the most robust things on the planet, it's probably 30Mb total of compile code. Now 175Mb for .NET 2.0 isn't huge, but the tools provided with it and the architecture of the framework itself does more than demonstrate how things should be organized in a production-quality system. Now of course I don't mean to imply that VB6 isn't enterprise ready, after all, many of the largest businesses in the country either have before or still today run entirely on VB6-based systems; I can't help thinking though of what could have come of those very same organizations had something like ASP.NET, Ruby on Rails, or the concept of "AJAX" had been around back during the original .com bubble.
Or what kind of "production-quality" code could be running this company if I weren't so confused as to why my controls aren't gaining focus when I click them...
Subscribe to:
Posts (Atom)