TweetFollow Us on Twitter

Modifying Objects At Runtime

Volume Number: 15 (1999)
Issue Number: 3
Column Tag: PowerPlant Workshop

Modifying Objects at Runtime in PowerPlant

By John C. Daub, Austin, Texas USA

A look at PowerPlant's Attachments mechanism

Welcome!

One of the things that makes the Mac so great and so much fun to use is the ability to customize your Mac just the way you like it. There are all sorts of cool functional utilities like Monaco Tuner/ProFont and FinderPop, and many cosmetic enhancers like the ubiquitous Kaleidoscope. Just how do these cool tools do the voodoo that they do so well? Through the magic of trap patching! Patching traps is a neat way to change the runtime behavior of an application and/or the OS itself without having to actually change the application or OS. Think of it like subclassing to implement new functionality for an object, but you didn't have to subclass to actually gain the new functionality - something else came in at runtime and modified the object's behavior.

If that explanation only served to further confuse you, I apologize. However, by the end of this article you will have a better understanding of the statement. You see, PowerPlant has a mechanism akin to patching called Attachments. Attachments are a way to modify the runtime behavior of PowerPlant objects, so in a sense it can be viewed as patching. By using PowerPlant's Attachments mechanism you can extend, limit, or otherwise change the behavior of a PowerPlant object at runtime, and all through a mechanism that's simple yet very powerful; in fact the theory of the Attachments mechanism will play a larger role throughout PowerPlant in future versions of the framework.

By the way, if you're curious about trap patching, check out a book like Dave Mark's Ultimate Mac Programming. Dave recruited Jorg Brown to write the chapter on trap patching, so you'll definitely be in good hands.

Overview

PowerPlant's Attachment mechanism is comprised of two parts: the Attachment's host and the Attachment itself.

Attachables

An object that can host Attachments is called an Attachable. The LAttachable class defines an Attachable object, and any class that inherits from LAttachable can have Attachments attached to it (you cannot attach Attachments to objects that are not Attachables). Within PowerPlant, LAttachable is used as a virtual base class for some key base objects: LCommander, LEventDispatcher, and LPane (see my introduction to PowerPlant article in the December 1998 MacTech or refer to the PowerPlant Book, Metrowerks' official documentation on PowerPlant, for an explanation of these classes)


Figure 1. LAttachable class hierarchy.

Although Figure 1 does not look like much, do not forget the great number of classes that inherit from LCommander and LEventDispatcher, and especially the multitude of classes that inherit from LPane (there was just no way to print such a large hierarchy within the constraints of this article). Since these key objects are Attachables, you can begin to see that many of PowerPlant's key behaviors can be modified through the use of Attachments.

The LAttachable class provides all the functionality a host needs to manage Attachments. One can AddAttachment() or RemoveAttachment() to add or remove Attachments from the Attachable's internal list of Attachments. If you're in a hurry, you can call RemoveAllAttachments() to remove all of an Attachable's Attachments. Accessors are provided to GetDefaultAttachable() and SetDefaultAttachable() (the default Attachable is the object to which an Attachment will be attached when it is created from a PPob DataStream). Finally LAttachable provides ExecuteAttachments() as the ever-important means to allow Attachments to carry out their task. Most of your interactions with LAttachable will be through AddAttachment() (and possibly RemoveAttachment()), as the rest is handled for you within PowerPlant itself. Of course the other part of the equation here are the Attachments themselves, so let's take a look at them.

Attachments

An Attachment is an object that can modify the runtime behavior of another object without having to modify that object itself. Through the use of Attachments, you can modify how an object: handles events, draws or prints, handles clicks and keypresses, adjusts the cursor, responds to commands and actions, and even how it finishes creating itself. Figure 2 presents the Attachment classes provided by PowerPlant.


Figure 2. LAttachment class hierarchy.

The points at which the Attachments are given the opportunity to modify the runtime behavior of its host object (i.e. the places within PowerPlant where LAttachable::ExecuteAttachments() is called) are well defined by the PowerPlant API. Since the intent of an Attachment is to modify the "normal" behavior of an object, this Attachment execution point occurs immediately before the host object executes its normal course of action. So just before that mouse click is given to the Pane object for processing, the Pane's Attachments are given first crack at the click. Listing 1 illustrates how this looks in code.

Listing 1: Attachment execution point

LPane::Click()
void
LPane::Click(
   SMouseDownEvent&      inMouseDown)
{
   if (!inMouseDown.delaySelect) {
   
      PortToLocalPoint(inMouseDown.whereLocal);
      
      UpdateClickCount(inMouseDown);
      
      if (ExecuteAttachments(msg_Click, &inMouseDown)) {
         ClickSelf(inMouseDown);
      }
   }
}

When Click() is called, a little housekeeping is performed, then just before the actual handling of the click is to occur (ClickSelf()), the Pane's Attachments execute and could veto the execution of the Pane's normal click functionality. We'll look at how all of this works in the next section.

Like the LAttachable class, the LAttachment class is also quite simple. It contains constructors and a destructor, as one would expect of a C++ class. One item to note is LAttachment has an LStream constructor, which means that Attachment objects, like Pane objects, can be constructed from a PPob DataStream. You can edit Attachments in Constructor, they have class_ID's, and must be registered (see URegistrar) if you create your Attachments in this manner. If you've worked with Panes in PPob's, this procedure should be familiar to you. If you're not familiar with this procedure, it is covered in the PowerPlant Book.

There are three data members in LAttachment: mOwnerHost, mMessage, and mExecuteHost (and all three have associated Get/Set accessor methods). The first data member, mOwnerHost, is a pointer to the Attachment's host object for easy reference. The mMessage data member stores the particular message that the Attachment is to respond to. Finally, the mExecuteHost member is a Boolean value which specifies if the host should continue to execute its normal course of action or not. In the next section you'll see how these data members come into play.

The remaining two methods in LAttachment are Execute() and ExecuteSelf(). This is where all of the action happens, so to better explain them let's take a look at just how the Attachment mechanism actually works.

How Does It Work?

As you saw in the previous sections, the LAttachable and LAttachment classes are fairly simple, and the mechanisms by which they are implemented and execute are fairly simple as well. As mentioned previously, an Attachable iterates its list of Attachments at a well-defined point asking them to execute and passing them any relevant information the Attachment may need in order to properly execute in the given context. Figure 3 summarizes those points within PowerPlant.


Figure 3. Attachment execution points.

When in the course of an application's events it becomes necessary to execute an Attachment (the Where Called column in Figure 3), the host iterates its list of Attachments asking each if it cares to do something relevant to the given situation; this is done by calling the Attachment's Execute() method. Within Execute() the Attachment checks the message given to it by its host; if that message is the same as the Attachment's mMessage (or is the special msg_AnyMessage), then Attachment then calls its ExecuteSelf() to do its voodoo. Within ExecuteSelf() the Attachment of course does whatever it does (respond to the click, handle the event, modify the host's cosmetics, etc.), but also must specify if upon returning the host should continue to execute its normal action or not by calling SetExecuteHost(). If the Attachment wishes to completely override the host's behavior, the Attachment should SetExecuteHost(false). If the Attachment wishes to merely augment the behavior, SetExecuteHost(true). Note this only affects the execution of the host action; if the host has other Attachments that have not yet executed, they will still execute.

That's all there is to how the Attachment mechanism works! It is such a simple mechanism, but so much can be accomplished through it. If you still don't believe me, there is an example application on the CodeWarrior Reference CD (the Attacher demo, part of the PP Mini Demos) and I've written a sampler to accompany this article as well (which should be on the MacTech web/ftp site). The Attacher demo shows how the mechanics of Attachments work, and my demo can show you all of the things you can do with Attachments.

Working With Attachments

Now that you understand how Attachments work, I'm sure you want to start to actually work with Attachments. Just as the mechanism itself is fairly simple, working with Attachments isn't very difficult either. The two primary areas in which you will work with Attachments is how to add/use them within your own projects, and how to create your own Attachments.

Adding Attachments

There are two ways to add an Attachment to an Attachable: on the fly or through a PPob. To add an Attachment on the fly you first create the Attachment via its "parameterized" constructor, then add it to a host by calling the host's AddAttachment() method. Listing 2 illustrates adding an LClipboard Attachment to your Application object (CApplication represents your Application object subclass, and remember that LApplication inherits from LCommander, which inherits from LAttachable).

Listing 2: Adding an Attachment on the fly

CApplication::Initialize()
void
CApplication::Initialize()
{
      // Create the LClipboard Attachment
   LClipboard*   theClipAttachment = new LClipboard;

      // Attach it to our Application object
   AddAttachment(theClipAttachment);
}

Although some Attachments, like LClipboard must be created and added on the fly as above, other Attachments can be created from a PPob DataStream (many Attachments support both creation mechanisms). Just like you can edit the Panes in your PPob's within Constructor for that wonderful WYSIWYG experience, you can add and edit some Attachments in Constructor as well.


Figure 4. Editing Attachments in Constructor.

As mentioned previously, to create your Attachment via the PPob DataStream, the Attachment must have an LStream constructor and a class_ID, just like Panes that you create from the PPob DataStream. As well, you must register your Attachment with URegistrar so the reanimation process will work correctly (again, for more information on PowerPlant's reanimation and registration mechanisms, consult the PowerPlant Book). If you create your Attachments in your PPob's, the Attachment is attached to whatever object it is hierarchically beneath. In Figure 4, the LWindowThemeAttachment will be attached to the LWindow; the LBeepAttachment is attached to the LStaticText. This is where the default attachable comes into play. Take a look at LAttachment's LStream constructor and the routines in UReanimator to see exactly how the default attachable is used.

In addition to editing Attachments in PPob's, you can also edit the CTYP information for the Attachment's themselves. By creating your own CTYP's for your Constructor objects, they'll appear in the Catalog window and can facilitate working in Constructor. Figure 5 shows the Constructor CTYP editor. Of course you can find more information on creating CTYP's and using Constructor in the Constructor Manual, Metrowerks documentation for Constructor.


Figure 5. Editing Attachment CTYP's in Constructor.

Creating your own Attachments

With what I've shown you so far, I hope you've been able to see just how simple it is to work with Attachments. But if there is anything difficult about Attachments it might be writing your own Attachment classes. The process itself isn't difficult - it's the first step of finding the behavior to implement that might throw you off a bit. Before you begin to write the Attachment you must design it well. You must decide what behavior you wish to implement, and then how it will fit into the Attachment mechanism: what message(s) to respond to; if the host should execute or not, and then under what circumstances to execute or not; if the Attachment can be created from a PPob DataStream; etc.

As soon as you have your design and goal(s) for the Attachment set, the implementation process is fairly short and simple. You need to have at least one constructor that allows the Attachment to be created on the fly. If the Attachment can be created from a PPob DataStream you must provide an LStream constructor and class_ID. Then implement your ExecuteSelf() to do the Attachment's magic, and you're done! In the implementation of ExecuteSelf(), be aware to SetExecuteHost() as needed. And if you wish to add that finishing touch, create a CTYP file for your Attachment so it can be easily edited within Constructor.

Take a look at the Attachments that PowerPlant provides, such as those in UAttachments.cp. There isn't much to their implementation, but as you use Attachments more and more you'll find yourself appreciating that simplicity. Conversely, if you look at my HCmdButtonAttachment (which is part of the demo application that accompanies this article), you'll see that Attachments aren't always lightweight, but the power they can bring makes them a great tool to have in your toolchest.

Why Use Attachments?

If you've made it this far, I hope that you've been able to gain an understanding of what Attachments are and just how they work within PowerPlant. You've seen the LAttachable and LAttachment classes, how the Attachments mechanism works, and how to build your own Attachments. But there is one question that remains: why would you use Attachments?

Remember that Attachments modify the runtime state and/or behavior of their host object. By being able to add to, remove from, or otherwise modify how an object behaves, you can do some nifty stuff and have a lot of code to reuse to boot. For example, a common feature in Mac applications today is the ability to simulate a mouse click on a button in a dialog with a keystroke; for instance, cmd-D could simulate a click on the "Don't Save" button in a "Save Changes" dialog. If you wanted to implement this behavior in a button class, you would subclass your main button class and implement the functionality to support the keystroke-as-click behavior. You did this for your PushButton class, but now you want the same functionality in your BevelButton class, so you have to reimplement the same code all over again. Then you want to have it in your CheckBox class, then your RadioButton class, and then you realize you want it in so many of your classes that it would be better to place it into a common parent class, but then this would break PowerPlant's existing inheritance chains so you would have to reimplement every single button widget you used... and you give up because this is getting ridiculous.

Consider the Attachment. You are implementing a behavior: handle a keystroke as if it was a click on a button (or any control for that matter). You create an Attachment that can intercept msg_KeyPress's, and whose ExecuteSelf(), upon receiving the correct keystroke calls SimulateHotSpotClick(), and you've now clicked the button without ever putting your hands on your mouse. Furthermore you've factored this behavior into stand-alone and reusable code. You can easily add this Attachment to your PushButtons, your BevelButtons, your RadioButtons, CheckBoxes, and any other Control you might desire. All the same code, no need to repeat nor reimplement the code, and no need to subclass anything - you can use stock objects. This is essentially what all Attachments do, and slightly more specific to this example, what the HCmdButtonAttachment Attachment does.

Attachments are also good for implementing new behaviors for legacy code. PowerPlant's Debugging Classes are centered around a menu that is added to your application's menubar and provides functionality to help debug and stress-test your application (see the Factory Floor column in the November, 1998 issue of MacTech for an overview of the Debugging Classes). Because the menu is implemented as an Attachment (LDebugMenuAttachment) it makes it quite simple to add and remove this functionality from an existing application. Furthermore, it enables you to have the Debug menu only in the debug builds of your application and not in your release builds. The modularity and "drop-in" capabilities of Attachments is another strength.

Conclusion

I hope you've been able to see what Attachments have to offer you as you continue you work with PowerPlant. If you have not used Attachments, do try the two demo applications and read over the various Attachment classes' source code; give them a try in your own applications. Most of the PowerPlant code that I've written recently has been Attachment based (e.g. LCMAttachment, LDebugMenuAttachment, HURLAttachment), and I find it to be one of the niftier and more flexible mechanisms that PowerPlant has to offer. After you're more familiar with Attachments, I'm sure you'll also find a place for them in your toolbox. What you can do with Attachments is pretty limitless, and after you write your first Attachment class I'm sure you'll agree with me.

Until next time... Happy programming!

Bibliography

  • Mark, Dave. Ultimate Mac Programming. Programmers Press, A Division of IDG Books Worldwide, Inc., Foster City, California. 1994.
  • Metrowerks Corporation. Constructor Manual. 1998.
  • Metrowerks Corporation. PowerPlant Book. 1998.
  • Metrowerks Corporation. PowerPlant Reference. 1998.
  • Monaco Tuner and ProFont: ftp://members.aol.com/squeegee/.
  • FinderPop: http://www.finderpop.com/.
  • Kaleidoscope: http://www.kaleidoscope.net/.

John C. Daub is one of Metrowerks Corporation's PowerPlant engineers. John wonders if you really care to know quirky biographical information about him, and if so, why? If you really want to know strange things about John or wish to ask him any questions (about PowerPlant or otherwise), you can reach John via email at hsoi@metrowerks.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

1Password 6.3.3 - Powerful password mana...
1Password is a password manager that uniquely brings you both security and convenience. It is the only program that provides anti-phishing protection and goes beyond password management by adding Web... Read more
Sublime Text 3126 - Sophisticated text e...
Sublime Text is a sophisticated text editor for code, markup, and prose. You'll love the slick user interface, extraordinary features, and amazing performance. Features Goto Anything. Use Goto... Read more
ForkLift 3.0 Beta 2 - Powerful file mana...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more
OmniFocus 2.7.1 - GTD task manager with...
OmniFocus helps you manage your tasks the way that you want, freeing you to focus your attention on the things that matter to you most. Capturing tasks and ideas is always a keyboard shortcut away in... Read more
CleanApp 5.1.1 - Application deinstaller...
CleanApp is an application deinstaller and archiver.... Your hard drive gets fuller day by day, but do you know why? CleanApp 5 provides you with insights how to reclaim disk space. There are... Read more
Together 3.6.1 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Features Smart storage. With simple drag-and-drop... Read more
Cloud 4.1.1 - File sharing from your men...
Cloud is simple file sharing for the Mac. Drag a file from your Mac to the CloudApp icon in the menubar and we take care of the rest. A link to the file will automatically be copied to your clipboard... Read more
Together 3.6.1 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Features Smart storage. With simple drag-and-drop... Read more
Cloud 4.1.1 - File sharing from your men...
Cloud is simple file sharing for the Mac. Drag a file from your Mac to the CloudApp icon in the menubar and we take care of the rest. A link to the file will automatically be copied to your clipboard... Read more
OmniFocus 2.7.1 - GTD task manager with...
OmniFocus helps you manage your tasks the way that you want, freeing you to focus your attention on the things that matter to you most. Capturing tasks and ideas is always a keyboard shortcut away in... Read more

Zip—Zap (Games)
Zip—Zap 1.01 Device: iOS Universal Category: Games Price: $1.99, Version: 1.01 (iTunes) Description: Touch to contract.Release to let go.Bring the clumsy mechanical beings home. · · · over 100 levelsno adsno in-app-purchases Zip—... | Read more »
Paperback: The Game (Games)
Paperback: The Game 1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: You are an author trying to finish kitschy paperback novels. Complete Westerns, Science Fiction, Romance or even a Crime... | Read more »
How to Rule With a Firm Hand in My Majes...
My Majesty is a kingdom management sim not unlike August’s magisterial hit, Reigns. It’s essentially a reskin of developer Tigrido’s previous management sim, Dictator. As supreme ruler of the land, you must consult with a number of subjects to... | Read more »
Our 5 Favorite iMessage Sticker Packs
At long last, iMessage joins the ranks of messaging apps the likes of LINE and Whatsapp, adding an impressive collection of stickers. They’re a great way to add a little something extra to your daily conversations. [Read more] | Read more »
How to get past Vulture Island's tr...
Vulture Island is a colorful and quirky mish-mash of platforming and puzzles. It’s creative and fresh, but sometimes the game can throw a curveball at you, leaving you stuck as to how you should progress. These tips will help you explore smoothly... | Read more »
The new Clash of Kings is just for Weste...
If you’ve played the original Clash of Kings, you’ll probably recognise the city building, alliance forging and strategic battles in Clash of Kings: The West. What sets this version apart is that it’s tailor made for a Western audience and the... | Read more »
Frost - Survival card game (Games)
Frost - Survival card game 1.12.1 Device: iOS Universal Category: Games Price: $3.99, Version: 1.12.1 (iTunes) Description: *Warning: the game will work on iPhone 5C and above and iPad Pro / 4. Other devices are not supported* | Read more »
How to build and care for your team in D...
Before you hit the trail and become a dog sledding legend, there’s actually a fair bit of prep work to be done. In Dog Sled Saga, you’re not only racing, you’re also building and caring for a team of furry friends. There’s a lot to consider—... | Read more »
How to win every race in Dog Sled Saga
If I had to guess, I’d say Dog Sled Saga is the most adorable racing game on the App Store right now. It’s a dog sled racing sim full of adorable, loyal puppies. Just look at those fluffy little tails wagging. Behind that cute, pixelated facade is... | Read more »
Let the war games commence in Gunship Ba...
Buzz Lightyear famously said, “This isn’t flying, this is falling – with style!” In the case of Gunship Battle: Second War, though, this really is flying - with style! The flight simulator app from Joycity puts you in control of 20 faithfully... | Read more »

Price Scanner via MacPrices.net

15-inch 2.2GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 15″ 2.2GHz Retina MacBook Pro (MJLQ2LL/A) on sale for $1799, including free shipping plus NY sales tax only. Amazon also has the 2015 15″ 2.2GHz Retina MacBook Pro (... Read more
Toughbook Celebrates 20 Years of Ruggedized M...
Panasonic System Communications Company of North America, Division of Panasonic Corporation of North America (Panasonic) today celebrates the 20th anniversary of its industry-leading Toughbook mobile... Read more
12-inch 1.1GHz Gray Retina MacBook on sale fo...
B&H Photo has the 2016 12″ 1.1GHz Gray Retina MacBook on sale for $1199.99 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
13-inch 2.5GHz MacBook Pro (Apple refurbished...
Apple has Certified Refurbished 13″ 2.5GHz MacBook Pros available for $829, or $270 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros... Read more
Save 30% on Camera Guard’s Secure Protection...
To celebrate the release of macOS Sierra, Miami-based security solutions company, ProtectStar has announced a special 30% discount on Camera Guard Professional for Mac 2016. This innovative security... Read more
DVDFab Special Deal – Get a 1-Year Free Licen...
Beijing, China based specialist in the field of DVD, Blu-ray and video backup solutions, Fengtao Software has launched its Autumn Special Deals 2016, giving a 1-year free license of a randomly picked... Read more
21-inch iMacs on sale for up to $120 off MSRP
B&H Photo has 21″ iMacs on sale for up to $120 off MSRP including free shipping plus NY sales tax only: - 21″ 3.1GHz iMac 4K: $1379 $120 off MSRP - 21″ 2.8GHz iMac: $1199.99 $100 off MSRP - 21″ 1... Read more
13-inch 2.7GHz/256GB Retina MacBook Pro on sa...
Amazon.com has the 13″ 2.7GHz/256GB Retina Apple MacBook Pro on sale for $151 off MSRP including free shipping: - 13″ 2.7GHz/256GB Retina MacBook Pro (sku MF840LL/A): $1348 $151 off MSRP Read more
Apple TVs on sale for up to $50 off MSRP
Best Buy has 32GB and 64GB Apple TVs on sale for $40-$50 off MSRP on their online store. Choose free shipping or free local store pickup (if available). Sale prices for online orders only, in-store... Read more
Apple refurbished 13-inch Retina MacBook Pros...
Apple has Certified Refurbished 13″ Retina MacBook Pros available for up to $270 off the cost of new models. An Apple one-year warranty is included with each model, and shipping is free: - 13″ 2.7GHz... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Sr. *Apple* Mac Engineer - Net2Source Inc....
…staffing, training and technology. We have following position open with our client. Sr. Apple Mac Engineer6+ Months CTH Start date : 19th Sept Travelling Job If Read more
*Apple* Retail - Multiple Positions-Norfolk,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.