|
SYS-CON.TV Webcasts
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Top Links You Must Click On
DataWindows Organize Your GUI with Layout Managers
Getting control over your windows
By: Christoph Menken
Apr. 30, 2005 09:45 AM
PowerBuilder novices know the problem as well as seasoned PowerBuilder developers. You build a window in the window painter. You arrange the controls on the window and the layout looks fine. Your users start the window and size it. It doesn't look fine any more because the components in the window don't fit the workspace. PowerBuilder doesn't resize automatically, so you have to build a resize service. The PowerBuilder window object delivers an event that resizes and positions the controls perfectly whenever the user resizes the window. But you have to code it yourself and adding controls expands the script in the resize event. Sure, you can implement it separately in functions, but you have to code it in all the windows you're using in your application. Copy and pasting is helpful, but a better way is to inherit the windows from a base window with a resize service implemented. To do this you have to program a generic resize service in the ancestor window. But not all your windows look the same, so you have to build different ancestors for different layouts. Another problem is how to change the layout without building a whole new window. Let's have a look how other programming languages or frameworks solve this problem. Let's adapt some of ideas from Java or C# and build some layout managers. What Is a Layout Manager?
Building a Layout Manager for PowerBuilder That doesn't mean there's no inheritance in the layout manager architecture. All the objects for the special layout styles have common functionality that's implemented in a common base object. We need an ancestor object for all layout managers that defines the base functionality as shown in Figure 1.
The whole idea is to lay out the controls in a window or user object. So we need a function to do this. The function has to lay out the container and arranges the controls. The container could be a window or another control like a tab page. Both are descendents from the graphic object type, so my first thought was to use this class for the common function for all graphic objects. But I am afraid we can't use this class because a graphic object doesn't have information about the position and size of the object. So we have to write two different functions, one for the class window and one for drag objects. The drag object is the ancestor class of all the controls in a window that can be containers for other controls (group boxes or user objects, for example). If you want to use a layout manager to draw objects like rectangles and ovals you have to build more functions in the ancestor class for the draw object type and perhaps for the mdiclient too. I chose to implement different functions for each container type to be sure that no wrong function calls are implemented because the compiler wouldn't accept them. Let's have a look on how it's defined for a drag object:
If you've got two or more functions to lay out different types of visual objects, as described above, you can consolidate your work by implementing a protected function of_layout(readonly graphicobject ago_parent), which will do the layout work. This function will be internally called by the different of_layoutcontainer functions (maybe four as described above). Here is the implementation for the window:
This is done this way to be sure that no wrong function calls are implemented, because the compiler won't accept them and you only have to implement the functionality once per layout manager. Notice that the function (of_layout) is a kind of virtual function in the n_cst_layoutmanager object, because all the layout managers we use are ultimately inherited from this base object. The function is coded in the descendants because this is the main function of the layout process and differs by type of layout manager. It's now time to think about telling the object which components to arrange. We can do this, for example, in the constructor event of the container with a function like this:
We store the components in an instance array (n_cst_component invo_component[]). To create this array we have to define the class for n_cst_component (see Figure 1) and a set of functions to make it work:
To remove a component from the list you have to implement the this function:
This is the base functionality of a layout manager, but it doesn't lay out anything yet. You can tell it which components it should lay out for which container. The defined function of_Layout is only a virtual function. You have to implement it in the specific layout manager type. Reader Feedback: Page 1 of 1
Enterprise Open Source Magazine Latest Stories . . .
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||