Gregor.UICore
Sunday, April 27, 2003
Gregor.UICore namespace
Action Lists
Implements some sort of action pattern, that is, placing common aspects of menu, toolbar buttons, and keyboard shortcuts into a single class (CAction). Then, there is a special toolbar class that allows identifiying buttons by string key; its buttons can be initialized from actions. Also, the owner-drawn menu items often talked about live in this namespace (the menu items can be used without actions, and vice versa, you can hook up actions to regular menu items with using my drawing code).
Image By String Key
Offers a special image list class that quickly picks up all resource icons embedded in an assembly, and makes them accessible by name. It's used with the action and control classes in this project.
Gregor.UICore.Controls namespace
Yet Another Toolbar
Features the XContainerBar class, which is a flexible toolbar that can host any control. It supports actions (from the Actions sub namespace), buttons, separators, and combo boxes by default. Its layout management allows for stretching a given item to make use of excess space, as well as displaying items in a menu if the space is too small. Action items can show text, icon, or both, and of course dropdown and toggle style items are taken care of as well. There is a built-in customization dialog, which lets the user edit item appearance, icons, and keyboard shortcuts. Container bars also support serialization. Both customization and serialization support are available for and extensible by custom bar items (which wrap up other types of controls).
Mixing Lists with Trees
Then, there is the XTreeListView class, an extenstion to WinForms.ListView. It supports displaying hierarchical data in a list view (the user may drill down, for example, into folders that are shown, see the XShellTreeView class in the Gregor.AppCore project). XTreeListView is similiar to the controls found in certain news readers, although the implementation is somewhat hacked (dare I not say "practical"?): icons are not indented, and there are no "+"/"-" icons for expanding and collapsing (but the arrow, plus/minus, and backspace keys as well as double-clicking, work), and the use of certain base class members (in particular, the Items property and the Sort() method) are illegal. XTreeListView also supports grouping in addition to sorting (groups can be shown in two ways: either as seperator items, or in a hierarchical way, using the drill-down functionality; see the NestGroups property).
Gregor.UICore.Dialogs namespace
Dialog Classes
Special form base classes for dialogs with various degree of specialty can be found here.
There are a few ready-to-use dialog classes as well, such as the FCombo class, which is a convenient way of receiving "choice" input using a combo box.
Gregor.UICore.Docking namespace
About Tool Windows
Has a wrapper class (CToolWindow) which adds docking capabilities to any form. The form need not worry about any aspect of it, and can be derived from any other form class. The same goes for hosting main windows. The CToolWindow class wraps a descendent of the class System.Windows.Forms.NativeWindow, hijacking the dockable form's handle. Everything else is managed by the XDockStrip and CDockManager classes, mostly.
Tool window capabilities include:
- Full-edge, single-row docking at any edge, including showing multiple tool windows docked to different edges.
- Parking an unlimited number of tool windows at any edge while they're hidden, then displaying special toggle buttons at the edge. The toggle buttons are drag-and-drop aware - this means you can drag data onto a tab and so activate a hidden tool window.
- When docked at an edge and visible, tool windows can either split the hosting form or hover above other controls.
- AutoHide behaviour (hiding when focus is lost) and AutoShow support (showing when the mouse is being moved over the toggle buttons at the edge). Both of these aspects may be configured independently of each other. If either action (showing or hiding) occurs automatically, windows are animated (slide animation).
- Floating state (like non-modal dialogs). In floating state, the AutoCollapse property lets the the tool window minimize in-place when it loses focus (being restored when it gains focus again).
- Fill state (like MDI windows), optionally including a VS-style tab strip. The tabs are drag-and-drop aware as well.
- Main Window state, using the Windows task bar. Optionally, tool windows can be owned by the main application window.
When docked to an edge, the host form is added a so-called "dock strip" having toggle buttons to show and hide the tool window. The toggle buttons on the dock strip can be rearranged by drag-and-drop (even across edges). They can show an icon and text (with the option of hiding the text when the tool window is hidden). Dock strips and their toggle buttons can be styled in a variety of ways (fonts, colors).
Tool windows have buttons in their title bar for toggling Hover (AutoHide) style like in Visual Studio. When docked, no borders are drawn, given a solid docking appearance.
Drag-and-Drop
The tool windows themselves can be dragged, too, using outline dragging (by painting on the desktop window using bitwise operations on pixels, which is encapsulated in the CDragRectangle class, driven by the CDragManager class).
Here's an overview of drag-and-drop in action, and toolwindows in serveral docking states.
Coding Example
Here's a sample of how to use docking. Note that any content on the hosting form must come through tool windows (the dock manager virtually owns it):
// set LIBS=Gregor.Core.dll,Gregor.UICore.dll,Gregor.AppCore.dll // csc.exe /debug+ /t:winexe /r:%LIBS% TestDocking.cs using System; using System.Drawing; using System.Windows.Forms; using Gregor.Core; using Gregor.UICore; using Gregor.UICore.Docking; using Gregor.AppCore; namespace Gregor { [Module()] public class TestDocking { [STAThread()] public static void Main(string[] args) { Dev.StopOnExceptions = true; Dev.AllowDetails = true; // the following line of code will be executed next: Application.Run(new FHost()); } } // module TestDocking public class FHost : Form { private CDockManager m_DockManager; public FHost() { this.Text = "Gregor.UICore.Docking Sample"; this.Size = new Size(500, 300); m_DockManager = new CDockManager(this, true); m_DockManager.FillContainer.FillStrip.StyleSet = CStyleSet.LightTabbed; this.AddToolWindow("Hello", "Property.ico", DockState.Fill); this.AddToolWindow("World", "Library.ico", DockState.Fill); this.AddToolWindow("Goodbye", "Event.ico", DockState.Right); this.AddToolWindow("Underworld", "Public.ico", DockState.Right); } private CToolWindowRestore AddToolWindow(string sText, string sIcon, DockState ds) { CToolWindowRestore twr = m_DockManager.ToolWindowRestores.Add( typeof(FTool), // type of user window sText, // key sText, // initial tool window text AppCoreStockIcons.ImageList, // image list (optional) sIcon // icon key in image list (optional) ); twr.Tooltip = twr.Text + " tool window"; twr.DockState = ds; twr.SetUserWindowCreateArgs(sText); // will be passed to constructor return twr; } protected override void OnLoad(EventArgs e) { try{ foreach(CToolWindowRestore twr in m_DockManager.ToolWindowRestores){ m_DockManager.ShowToolWindow(twr.Key); } }catch(Exception ex){ Dev.ProcessException(ex); }finally{ base.OnLoad(e); } } } // class FHost public class FTool : Form { public FTool(string sText) : base() { TextBox txt = new TextBox(); txt.Multiline = true; txt.Dock = DockStyle.Fill; txt.Text = sText; this.Controls.Add(txt); } } // class FTool } // namespace Gregor