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

Latest Forum Discussions

See All

Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »

Price Scanner via MacPrices.net

Apple Watch Ultra 2 now available at Apple fo...
Apple has, for the first time, begun offering Certified Refurbished Apple Watch Ultra 2 models in their online store for $679, or $120 off MSRP. Each Watch includes Apple’s standard one-year warranty... Read more
AT&T has the iPhone 14 on sale for only $...
AT&T has the 128GB Apple iPhone 14 available for only $5.99 per month for new and existing customers when you activate unlimited service and use AT&T’s 36 month installment plan. The fine... Read more
Amazon is offering a $100 discount on every M...
Amazon is offering a $100 instant discount on each configuration of Apple’s new 13″ M3 MacBook Air, in Midnight, this weekend. These are the lowest prices currently available for new 13″ M3 MacBook... Read more
You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14″ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
24-inch M1 iMacs available at Apple starting...
Apple has clearance M1 iMacs available in their Certified Refurbished store starting at $1049 and ranging up to $300 off original MSRP. Each iMac is in like-new condition and comes with Apple’s... Read more
Walmart continues to offer $699 13-inch M1 Ma...
Walmart continues to offer new Apple 13″ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBook for sale by... Read more
B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13″ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Apple’s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14″ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: – Mac mini M2/256GB SSD: $499, save $100 – Mac mini M2/512GB SSD: $699, save $100 –... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazon’s stock tends to come and go: – 14″ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more

Jobs Board

*Apple* Systems Administrator - JAMF - Syste...
Title: Apple Systems Administrator - JAMF ALTA is supporting a direct hire opportunity. This position is 100% Onsite for initial 3-6 months and then remote 1-2 Read more
Relationship Banker - *Apple* Valley Financ...
Relationship Banker - Apple Valley Financial Center APPLE VALLEY, Minnesota **Job Description:** At Bank of America, we are guided by a common purpose to help Read more
IN6728 Optometrist- *Apple* Valley, CA- Tar...
Date: Apr 9, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92308 **Requisition ID:** 824398 At Target Optical, we help people see and look great - and Read more
Medical Assistant - Orthopedics *Apple* Hil...
Medical Assistant - Orthopedics Apple Hill York Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
*Apple* Systems Administrator - JAMF - Activ...
…**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.