An Introduction to Blocks: As Seen at Chandler Startup
Trees of Blocks and the MainViewRoot
Blocks are organized in the repository in
trees where the Block's
childrenBlocks attribute points to the block's children and the
parentBlock attribute points to its parent Block.
When Chandler starts, it locates the block that is at the root of the user interface, the
MainViewRoot Block.
The MainViewRoot Block is a BoxContainer (actually it's a subclass of BoxContainer, which is almost identical to a BoxContainer). BoxContainers organize their children Blocks (who derive from the RectangularChild class) in a rectangular space on the screen. BoxContainers can contain other BoxContainers. For example, there is a BoxContainer, the ToolbarContainer, that contains the ApplicationBar Block and another BoxContainer that contains a container that contains the Sidebar Block.
An attribute on the BoxContainer specifies whether its children are laid out vertically or horizontally. Attributes on the children of BoxContainers, like size, border, alignment and stretchFactor control how the child is located relative to its siblings in the BoxContainer and how its size changes as its parent BoxContainer's size changes.
The BoxContainer's widget wxBoxContainer is the wxWidgets wxBoxSizer, so if you understand how sizers work in wxWidgets you'll understand BoxContainers and RectangularChildren.
Here's an abbreviated outline view of the MainViewRoot, where each line show the name of the Block followed by its class and child Blocks are listed indented below their parent :
MainViewRoot FrameWindow
MainBPB BranchPointBlock
MainView MainView
MenuBar MenuBar
FileMenu Menu
NewItemMenu Menu
NewNoteItem MenuItem
NewMessageItem MenuItem
NewTaskItem MenuItem
NewEventItem MenuItem
NewSeparator1 MenuItem
NewContactItem MenuItem
FileSeparator1 MenuItem
NewCollectionItem MenuItem
NewCollectionItem MenuItem
...
...
StatusBar StatusBar
ReminderTimer ReminderTimer
BoxContainer ToolbarContainer
BoxContainer Toolbar
ApplicationBarAllButton ToolbarItem
ApplicationBarMailButton ToolbarItem
ApplicationBarTaskButton ToolbarItem
ApplicationBarEventButton ToolbarItem
...
SidebarContainerContainer BoxContainer
SidebarContainer SplitterWindow
Sidebar Sidebar
PreviewAndMiniCalendar BoxContainer
PreviewArea PreviewArea
MiniCalendar MiniCalendar
SidebarBPB BranchPointBlock
Rendering Blocks
The MainViewRoot has a single child block, the MainBranchPointBlock (we'll explain BranchPoint blocks in a moment) whose child is the MainView. The MainView is the root of the Chandler user interface you normally see. To display the MainView tree, or any other tree of Blocks, it first needs to be "rendered."
Since Widgets don't persist, they don't exist at startup like Blocks, so the rendering process traverses the tree top down, creating a Widget for each Block (by calling the instantiateWidget method on the Block). Rendering adds the
widget attribute to the block that points to the widget and the
blockItem attribute to the Block, that points to the widget. If the Block has contents, it is subscribed to be notified of changes to the contents.
After the widget is created, while returning up the tree, synchronizeWidget is called on each Block. This causes the state of the widget to match the Block, i.e. the View matches the Model (using the MVC paradigm).
After rendering, the user interface is visible on the screen.
When the user interface is no longer displayed it is unrendered, which does the opposite of render: deletes the widgets, removes the widget attribute and unsubscribes the Block to its contents.
The MainView's Children
If you look further into the tree of Blocks rooted at the MainView, you'll notice that its children Blocks include the MenuBar, StatusBar, ReminderTimer, and ToolbarContainer.
The MenuBar's children include the Menus, which in turn include other Menus and MenuItems etc.
The ToolbarContainer contains the ApplicationBar and the Sidebar's container. The ApplicationBar is a Toolbar Block, whose children are the ToolbarItem Blocks.
The MenuItems and ToolbarItems
MenuItems and ToolbarItems can be located anywhere in the tree of blocks -- they don't need to be children Blocks of their Menu or Toolbar. This allows MenuItems and ToolbarItems to come and go dynamically as new user interface comes and goes (or trees of Blocks are rendered and unrendered).
The MenuItem and ToolbarItem specify which menu or Toolbar they are associated with using their dynamicParent attribute. Their operation enum attribute controls whether the item is appended to the Menu/Toolbar, inserted before another item in the Menu/Toolbar, replaces another item in the Menu/Toolbar, or removes an existing item in the menu Toolbar.
Note : Expect the implementation of ContextMenus and ContextMenuItems to change. They should be refactored to be Menus and MenuItems so they can take advantage of the features of the existing Menu code.
Besides attributes that describe the MenuItem and ToolbarItem (e.g.
title and
help string) each Item refers to a BlockEvent. When the MenuItem or ToolbarItem is chosen by the user, the BlockEvent is dispatched according to a method determined by its attributes to a Block that handles the event.
Most Chandler specific commands in menus are handled by the MainView Block.
Other Common Blocks
Like Menus and Toolbars, many kinds of Blocks map closely to a particular kind of wxWidget, including List, Table, Tree and SplitterWindow.
Attribute Editor Blocks (AEBlocks), on the other hand don't. They are used to edit a particular attribute of a particular item. The attribute editor uses the type of the attribute along with style hint to chooses the correct user interface to display and edit the attribute. This allows an attribute editors to adapt to changes to the type of the attribute. Attribute editors are used everywhere attributes are edited outside dialogs: currently, the sidebar, summary view and detail view.
Note : In the 0.6 release some unused Blocks are broken, including TabbedContainer and TabbedView. Also some Blocks will be going away in the future, including Button, Checkbox, ComboBox, Choice, EditText, HTML and StaticText, which will be replaced by AttributeEditors.
BranchPoint Blocks
It's sometimes necessary to substitute new user interface in part of a window. This happens in Chandler when you click on an Item in the SummaryView and you see a new DetailView view or when you click in the Sidebar and the Summary View changes.
The
BranchPointBlock with its controller delegate is responsible for replacing a rectangular area of the user interface with a new tree of Blocks (user interface).
The delegate, which is a persistent Item but not a Block, contains the sometimes complicated logic that determines which tree of block is used, building it if necessary, and caching it to be reused later. Reusing the cached copy makes it possible for the state of the user interface to be maintained when you return to it. Because the controller determines what UI is displayed for an item in response to a user action, it is similar to a Controller in the MVC paradigm.
Chandler currently has 3 BranchPoint blocks :
- TableSummaryDetailBPB lives in the Summary View and substitutes the appropriate Detail View.
- SidebarBPB lives in the Sidebar and substitutes the appropriate Summary/DetailView.
- MainBPB lives just below the MainViewRoot and is used to substitute new or slightly different user interfaces for testing.