TweetFollow Us on Twitter

First Steps Volume Number: 17 (2001)
Issue Number: 4
Column Tag: PowerPlant Workshop

First Steps

By Aaron Montgomery

How one goes about writing a PowerPlant application

My Intended Audience

This series of articles is intended to be an introduction into the use of the PowerPlant application framework. It is intended to be a gentler introduction than The PowerPlant Book supplied on the CodeWarrior CD and more elementary than previous MacTech articles (in particular, those by John C. Daub). We will start by building a very basic application in this article and we will add features to it in later articles (upcoming articles are planned on the topics of: debugging, windows, files, dialogs, preferences, and panes).

PowerPlant is big and it would be hard (if not impossible) to try to provide a simple linear introduction to the topic. As a result, these articles are likely to introduce some aspect of the framework without fully explaining how it works. In some cases, the series will make a concerted effort to return to the topic but in other cases the reader will be expected to do a little reading on their own. One consequence of this is that it will probably be worthwhile to re-read earlier articles after finishing with the later articles. Another consequence is that often I will introduce a term without explanation and you may need to read more of the article before it makes sense.

While writing this article, I've assumed that the readers are familiar with the C++ programming language and basic Macintosh API programming topics. In addition to these programming skills, readers are also assumed to be familiar with the CodeWarrior IDE (including the use of the class browser and debugger).


Before you start reading this article, it is best to know where I learned what I know. I program as a hobby (not as a profession) and have been using PowerPlant in my projects for the past three years. Although I consider myself fairly adept with the framework, I don't claim to know all the details. I encourage those who know the framework better to contact me if I make any errors or miss any topics. Probably the best forum for this is the PowerPlant newsgroup and I will also post errata at my web site (see by-line).

Why Learn PowerPlant

PowerPlant is an application framework. You can find a detailed discussion of what this means in The PowerPlant Book, but basically, this means that it provides much of the routine code needed for a Macintosh application (in particular, the interface) and allows you to focus on the details of your specific program. At the time that I am writing this, a natural question arises: why bother with PowerPlant when you could use Cocoa? Personally, I decided to continue to use PowerPlant for two reasons. The first of which is my own personal familiarity with C++. Since I only program as a hobby, I don't have the time (or the need) to build that level of familiarity with Objective C and would like to continue to use a language I know. A second reason is that many of the programs I write for educational purposes will be used in environments where OS X is not going to be available for a number of years. PowerPlant allows me to use a single code-base to support a wide variety of platforms (from 68K to G4).

The Tools

This article will assume that you are using CodeWarrior 6 with the net-update to IDE and no other modifications. In particular, it assumes the use of Universal Headers 3.3.2 and no modified PowerPlant files. I believe much of the code I write should also run on CodeWarrior 5 or with newer Universal Headers without much trouble (other than that caused by the Metrowerks' PowerPlant source). If you are trying to use these articles as a guide and run into trouble with a particular configuration, let me know and I will try to suggest a solution.

Stationary Options

The first thing to do with any project is to create a new project file from the Metrowerks supplied stationary. There are four options: Basic, Appearance, Document or Advanced. The Basic option is the simplest and all other options are built on top of it. The Document and Appearance options have identical library source file and include everything in the Basic option as well as the Appearance Classes, the Graphic Utilities, the Grayscale Classes and the Page Controller. The difference between the two versions is that the sample code for the Document option is set up for a basic application supporting the use of documents. The Advanced option contains everything in the Document and Appearance options as well as the Context Menu, the Debugging Classes, the Table Classes and the Threads Classes. This is the option I choose most frequently (the Debugging Classes are so good, they will be the topic of the second article in this series).

For this project, I started with the Advanced option, moved some unused classes out of the regular targets to a side-target (Other Stuff). We'll add them back to the build targets when I start using them in later projects. I have also made some stylistic changes (e.g., requiring explicit use of the PowerPlant namespace and adding a separate file to contain main()). Finally, I removed some code so that I will be able to focus on the basics. Much of the removed code will reappear in later articles.

Naming Conventions

Before examining any source code, the PowerPlant naming conventions deserve mention. All PowerPlant types defined by typedef macros end with a T. All PowerPlant classes begin with L (for library), U (for utility) or St (for stack-based). Class methods begin with uppercase letters and use capitalization as a word-break. Class data (static data) begins with the letter s and object data begins with the letter m. Calls to the Macintosh API are indicated by a global scope operator (::). Local variables are indicated by the prefix the. You can find more conventions in The PowerPlant Book.

User classes (those that you write) will typically start with a C (for class), I also use Ut (for utility) and Au (for automatic, i.e., stack-based) classes. Class data for my classes begins with our and object data begins with my. This helps me distinguish between data I am responsible for and data coming from the framework.

Browsing the Initialization Code

The first code we will discuss is the function main() in main.cp. One effective way to learn about PowerPlant is to use the class browser to examine a function's definition and commentary. In order to follow along, you will need to make the project with the class browser activated (see the Build Extras preference panel for the target). I will be using the PPC Debug target although you may want to use a different target depending on your setup. (I have removed all comments for listing in the magazine.)

main() in main.cp

int main()
   ::FlushEvents(everyEvent, nil);

   CDocumentApp   theApp;
   return 0;

We'll quickly run through the initialization code in main() using the browser. Selecting the InitializeHeap() (e.g., by double-clicking the word) and then using Find Definition in the Search (or by using command-'), we can get the source for the function. PowerPlant commentary is good and the comments before the definition of InitializeHeap() describe its purpose: it expands the heap and calls the appropriate version of MoreMasters(). The next method is InitializeToolbox() and looking at its definition (and code commentary) you can see that it contains the standard Macintosh Toolbox initialization code. Following the toolbox initialization is a ::FlushEvents() call. This isn't called in the InitializeToolbox() method, but commentary in the PowerPlant stationary indicates that failure to call it may lead to problems and so we place it here. The last call in this sequence is InitEnvironment(). Looking at its definition (and code commentary) indicates that it will check for things like the existence of the Appearance Manager. Even if you do not use the UEnvironment class yourself, PowerPlant uses it and so you need to insure that it is initialized.

We have now reached the class CDocumentApp. This class represents the Macintosh application and the object theApp represents this instantiation of the Macintosh application. Again, we can use the browser to examine the constructor.

CDocumentApp() in CDocumentApp.cp

   if (UEnvironment::HasFeature(env_HasAppearance))


The HasFeature() determines if the Appearance Manager is installed. If it is installed, the application registers itself with the operating system. The second statement is a call to the static method RegisterClasses() of CTextDocument. This is necessary to build the window structure from the resource file and will be discussed in the third article.

Stepping Through Run()

The browser is good if the code is very linear, once the code becomes complicated, stepping through the source with the debugger can be a great aid in understanding. In order to do this, add a breakpoint on the line CDocApplication.Run() call in main.cp and run the application (with the debugger enabled). When the debugger halts at this breakpoint, step into the Run() method. I will describe, but won't list, the code from the PowerPlant source. The first thing that occurs is a sequence of initializations for the application: creating a menu bar, setting up the AppleEvent handlers and then calling Initialize(). This virtual method should handle initialization routines that need to happen after the menu bar and AppleEvent handlers have been initialized (and hence cannot occur in the constructor). Later we will use this method to create a dynamic menu, for now we fall back on the inherited method. PowerPlant then calls ForceTargetSwitch() (described below), initializes the cursor, updates the menu and starts handling events.

Event Processing

We have now reached the main event loop. There are two types of events to which the application needs to respond: AppleEvents and menu-commands. The PowerPlant framework handles the dispatching of some basic AppleEvents to virtual methods in the LApplication class. The only ones we need to implement here are the methods associated with Open Application and Reopen Application events. PowerPlant dispatches these to the StartUp() and ReopenApp() methods respectively.

StartUp() and ReopenApp() in CDocumentApp.cp
   ObeyCommand(cmd_New, nil);

   if ((UDesktop::FetchTopRegular() == nil)
         && (UDesktop::FetchTopModal() == nil))
      ObeyCommand(cmd_New, nil);

The basic idea of both methods is the same: pass the responsibility to ObeyCommand(). There only difference is that in ReopenApp(), the ObeyCommand() is only called if no other windows are open. In the actual source file, there is a long commentary about why this is the appropriate behavior.

The method ObeyCommand() is a virtual method of the LCommander class (from which LApplication inherits). Each LCommander has a supercommander (well, not quite, the top commander will not have a supercommander). The collection of commanders generated by following supercommanders up to the top commander is called the command chain. At any given time, exactly one LCommander object has control of the application, this object is said to be on duty. The call to ForceTargetSwitch() that we saw above placed the application object on duty. When ObeyCommand() is called, the object on duty should either obey the command or pass it to its base class. A basic example of this in this application is the cmd_New when no windows are open. To see how this is handled, place a breakpoint at the top of the ObeyCommand() method in LDocApplication (you can find this by typing command-' when no text is selected and typing ObeyCommand). Once the breakpoint is set, switch to the application (or start it from the debugger) and select Open from the File menu. You should step into the SendAECreateDocument() and MakeNewDocument() methods, the second is supplied by the CDocumentApp class.

MakeNewDocument() in CDocumentApp.cp
   return new CTextDocument(this);

That was simple, we just pass all the work off to the CTextDocument class. We will leave CDocumentApp for a moment and explore the CTextDocument class.

CTextDocument() from CTextDocument.cp

   LCommander*      inSuper)
   : LSingleDoc(inSuper)
   mWindow = LWindow::CreateWindow(PPob_TextWindow, this );
   myTextView =


Much of the code in the constructor handles the user interface and will be discussed in greater detail in the third article. We focus on those calls that concern the command chain. The CreateWindow() method creates a LWindow from data in the resource fork of the application. LWindow is derived from LCommander and the second argument in the CreateWindow() method sets the window object's supercommander. The window resource contains a LTextEditView and LTextEditView also inherits from LCommander and its supercommander will be set to the LWindow being created. The next two lines find the LTextEditView and then establish it as being the on duty when the window opens. The remaining two calls are mundane: NameNewDoc() uses a very naive method to generate unique window names (which will be improved in the third article) and Show() makes the window visible.

Now that we have a non-trivial command chain, we can demonstrate what happens when an object cannot obey a command. In this case, the command works it way up to the ObeyCommand() implementation in LCommander and you should place a breakpoint in that method. Now make sure a window is open in the application and select the Close item from the File menu. The first time you stop in LCommander's ObeyCommand(), a LTextEditView has received the command and is passing it upward to its supercommander. Running the debugger will cause the window to close and the application to continue. This means that the LWindow object was able to handle the command.

A good question arises here: If the LWindow handled the close event, what happened to the CTextDocument? To determine this, place a break point in the CTextDocument destructor and close another window. Before looking at the destructor code, examine the stack. By selecting on various locations of the stack you can see that the LDocument object's Close() method is called which causes the CTextDocument object to be destructed.

~CTextDocument() in CTextDocument.cp

   catch (...)

The destructor is very simple and only calls TakeOffDuty() which is inherited from LCommander. This call takes the CTextDocument off duty (a good thing since its memory is about to be reclaimed).

To see a more complicated demonstration of the command chain, make sure a breakpoint is still set in LCommander's implementation of ObeyCommand(). Now make sure a window is open and chose Quit from the File menu. This command will need to work up many levels in the command chain. The LTextEditView object passes it to the LWindow object which passes it to the LDocument object which passes it on to the LApplication object which causes the application to quit.

Menu Manipulation

The other virtual method that you will need to override when you add (or remove) commands is FindCommandStatus(). We will discuss this more fully in a later article when we handle menu management, but for now we only need to worry about the first two parameters. The first, inCommand, is of type CommandT and is the command whose status is being determined. The second, outEnabled, is of type Boolean& and will be set to true if the LCommander object can handle the command. Each time the menus are displayed, the method FindCommandStatus() is called in a manner analogous to ObeyCommand(). If any LCommander in the command chain can handle the command, the method returns true and the menu item is enabled. If no LCommander in the command chain can handle the command, the method will return false and the menu item will be disabled. Because they are called in identical ways, ObeyCommand() and FindCommandStatus() need to be consistent in each class.

FindCommandStatus() in CDocumentApp.cp

   CommandT   inCommand,
   Boolean&   outEnabled,
   Boolean&   outUsesMark,
   UInt16&   outMark,
   Str255      outName)
   switch (inCommand)
      case cmd_Open:
outEnabled = false;
inCommand, outEnabled, outUsesMark,
outMark, outName);

The PowerPlant class LDocApplication assumes the application will have the ability to open documents. Since we aren't going to implement this until we discuss files (in the fourth article), we need to disable the command in the File menu. We simply set outEnabled to indicate that the command is never handled and the item will remain disabled. Similarly, the CTextDocument overrides its FindCommandStatus() method to disable the cmd_Save, cmd_SaveAs and cmd_Print commands. You can trace this method in exactly the same way as we did for ObeyCommand(), but that will be left as an exercise for the reader.

Concluding Remarks

If you've followed along so far, you should be able to start examining some of the command chains in the sample projects that are provided on the CodeWarrior CD. You might also want to start reading through the references I present at the end of this article. The next article will discuss PowerPlant's debugging classes. Following that we will expand on PowerPlant's document classes (windows in the third article and files in the fourth article).

PowerPlant References

The PowerPlant Book on the CodeWarrior CD is an introduction to PowerPlant provided by Metrowerks. Unlike this series of articles, The PowerPlant Book focuses on the interface building aspects of PowerPlant first. If you need to obtain a high level of proficiency with PowerPlant, this is the book to work from cover to cover. The PowerPlant Advanced Topics book on the CodeWarrior CD continues where The PowerPlant Book leaves off. It covers more complicated classes such as the Drag & Drop Classes, Thread Classes and Networking Classes to name a few. The topics are presented so that you will be able to read each chapter as you need it (and not necessarily in a sequential order). Together these books constitute the primary texts for learning PowerPlant.

The PowerPlant Reference on the CodeWarrior CD provides documentation for most of the PowerPlant classes. I found this useful for a short period of time while learning PowerPlant, but after a few months I began to rely more on the class browser, the actual source, and the commentary in the source instead of the reference book.

If you have access to old MacTech articles, the "From the Factory Floor" articles in the October, November and December 1998 issues discuss PowerPlant. The first two of these start with a "How would you learn PowerPlant" question. John C. Daub also wrote a series of MacTech articles from December 1998 through June 1999 which cover individual components of PowerPlant (but do not cover the basic classes). The MacTech issues from 1999 are available online, but the 1998 articles were not up when I checked. You will want to search the article archives at <>.

Finally you might be able to find a PowerPlant class at Metrowerk's CodeWarrior U site <>. These courses tend to follow The PowerPlant Book.

Aaron teaches in the Mathematics Department at Central Washington University in Ellensburg, WA. Outside of his job, he spends time riding his mountain bike, watching movies and entertaining his wife and two sons. You can email him at, try to catch his attention in the newsgroup comp.sys.mac.oop.powerplant or visit his web site at


Community Search:
MacTech Search:

Software Updates via MacUpdate

Apple Safari 10.0.1 - Apple's Web b...
Note: The direct download link is currently unavailable. It is available in the OS X 10.11.6 release, as well as in the Apple Security Updates. Apple Safari is Apple's web browser that comes with OS... Read more
Apple macOS Sierra 10.12.1 - The latest...
With Apple macOS Sierra, Siri makes its debut on Mac, with new features designed just for the desktop. Your Mac works with iCloud and your Apple devices in smart new ways, and intelligent... Read more
Apple iOS 10.1 - The latest version of A...
iOS 10 is the biggest release of iOS ever. A massive update to Messages brings the power of the App Store to your conversations and makes messaging more personal than ever. Find your route with... Read more
Hazel 4.0.7 - Create rules for organizin...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a familiar... Read more
Opera 40.0.2308.90 - High-performance We...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
BetterTouchTool 1.93 - Customize Multi-T...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
Backblaze - Online backup serv...
Backblaze is an online backup service designed from the ground-up for the Mac. With unlimited storage available for $5 per month, as well as a free 15-day trial, peace of mind is within reach with... Read more
Postbox 5.0.5 - Powerful and flexible em...
Postbox is a new email application that helps you organize your work life and get stuff done. It has all the elegance and simplicity of Apple Mail, but with more power and flexibility to manage even... Read more
Coda 2.5.19 - One-window Web development...
Coda is a powerful Web editor that puts everything in one place. An editor. Terminal. CSS. Files. With Coda 2, we went beyond expectations. With loads of new, much-requested features, a few surprises... Read more
Toast Titanium 15.1 - $99.99
Roxio Toast 15 Titanium, the leading DVD burner for Mac, makes burning even better, adding Roxio Secure Burn to protect your files on disc and USB in Mac- or Windows-compatible formats. Get more... Read more

Latest Forum Discussions

See All

WitchSpring2 (Games)
WitchSpring2 1.27 Device: iOS Universal Category: Games Price: $3.99, Version: 1.27 (iTunes) Description: This is the story of Luna, the Moonlight Witch as she sets out into the world. This is a sequel to Witch Spring. Witch Spring 2... | Read more »
4 popular apps getting a Halloween makeo...
'Tis the season for all things spooky. So much, so, in fact, that even apps are getting into the spirt of things, dressing up in costume and spreading jack o' lanterns all about the place. These updates bring frightening new character skins, scary... | Read more »
Pokémon GO celebrates Halloween with can...
The folks behind Pokémon GO have some exciting things planned for their Halloween celebration, the first in-game event since it launched back in July. Starting October 26 and ending on November 1, trainers will be running into large numbers of... | Read more »
Best Fiends Forever Guide: How to collec...
The fiendship in Seriously's hit Best Fiends has been upgraded this time around in Best Fiends Forever. It’s a fast-paced clicker with lots of color and style--kind of reminiscent of a ‘90s animal mascot game like Crash Bandicoot. The game... | Read more »
5 apps for the budding mixologist
Creating your own cocktails is something of an art form, requiring a knack for unique tastes and devising interesting combinations. It's easy to get started right in your own kitchen, though, even if you're a complete beginner. Try using one of... | Read more »
5 mobile strategy games to try when you...
Strategy enthusiasts everywhere are celebrating the release of Civilization VI this week, and so far everyone seems pretty satisfied with the first full release in the series since 2010. The series has always been about ultra-addictive gameplay... | Read more »
Popclaire talk to us about why The Virus...
Humanity has succumbed to a virus that’s spread throughout the world. Now the dead have risen with a hunger for human flesh, and all that remain are a few survivors. One of those survivors has just called you for help. That’s the plot in POPCLAIRE’... | Read more »
Oceans & Empires preview build sets...
Hugely ambitious sea battler Oceans & Empires is available to play in preview form now on Google Play - but download it quickly, as it’s setting sail away in just a few days. [Read more] | Read more »
Rusty Lake: Roots (Games)
Rusty Lake: Roots 1.1.4 Device: iOS Universal Category: Games Price: $2.99, Version: 1.1.4 (iTunes) Description: James Vanderboom's life drastically changes when he plants a special seed in the garden of the house he has inherited.... | Read more »
Flippy Bottle Extreme! and 3 other physi...
Flippy Bottle Extreme! takes on the bottle flipping craze with a bunch of increasingly tricky physics platforming puzzles. It's difficult and highly frustrating, but also addictive. When you begin to master the game, the sense of achievement is... | Read more »

Price Scanner via

Apple’s Thursday “Hello Again” Event A Largel...
KGI Securities analyst Ming-Chi Kuo, who has a strong record of Apple hardware prediction accuracy, forecasts in a new note to investors released late last week that a long-overdue redo of the... Read more
12-inch Retina MacBooks on sale for $100 off...
Amazon has 2016 12″ Apple Retina MacBooks on sale for $100 off MSRP. Shipping is free: - 12″ 1.1GHz Silver Retina MacBook: $1199.99 $100 off MSRP - 12″ 1.1GHz Gold Retina MacBook: $1199.99 $100 off... Read more
Save up to $600 with Apple refurbished Mac Pr...
Apple has Certified Refurbished Mac Pros available for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The following... Read more
PixelStyle Inexpensive Photo Editor For Mac W...
PixelStyle is an all-in-one Mac Photo Editor with a huge range of high-end filters including lighting, blurs, distortions, tilt-shift, shadows, glows and so forth. PixelStyle Photo Editor for Mac... Read more
13-inch MacBook Airs on sale for $100-$140 of...
B&H has 13″ MacBook Airs on sale for $100-$140 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $899 $100 off... Read more
2.8GHz Mac mini available for $988, includes...
Adorama has the 2.8GHz Mac mini available for $988, $11 off MSRP, including a free copy of Apple’s 3-Year AppleCare Protection Plan. Shipping is free, and Adorama charges sales tax in NY & NJ... Read more
21-inch 3.1GHz 4K on sale for $1379, $120 off...
Adorama has the 21″ 3.1GHz 4K iMac on sale $1379.99. Shipping is free, and Adorama charges NY & NJ sales tax only. Their price is $120 off MSRP. To purchase an iMac at this price, you must first... Read more
Check Apple prices on any device with the iTr...
MacPrices is proud to offer readers a free iOS app (iPhones, iPads, & iPod touch) and Android app (Google Play and Amazon App Store) called iTracx, which allows you to glance at today’s lowest... Read more
Apple, Samsung, Lead J.D. Power Smartphone Sa...
Customer satisfaction is much higher among smartphone owners currently subscribing to full-service wireless carriers, compared with those purchasing service through a non-contract carrier, according... Read more
Select 9-inch Apple WiFi iPad Pros on sale fo...
B&H Photo has select 9.7″ Apple WiFi iPad Pros on sale for up to $50 off MSRP, each including free shipping. B&H charges sales tax in NY only: - 9″ Space Gray 256GB WiFi iPad Pro: $799 $0 off... Read more

Jobs Board

Software Engineering Intern: Integration / QA...
Job Summary Apple is currently seeking enthusiastic interns who can work full-time for a minimum of 12-weeks between Fall 2015 and Summer 2016. Our software Read more
Software Engineering Intern: Frameworks at *...
Job Summary Apple is currently seeking enthusiastic interns who can work full-time for a minimum of 12-weeks between Fall 2015 and Summer 2016. Our software Read more
*Apple* Retail - Multiple Positions- Nashua,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions- Napervi...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Security Data Analyst - *Apple* Information...
…data sources need to be collected to allow Information Security to better protect Apple employees and customers from a wide range of threats.Act as the subject Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.