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

PDFKey Pro 4.3 - Edit and print password...
PDFKey Pro can unlock PDF documents protected for printing and copying when you've forgotten your password. It can now also protect your PDF files with a password to prevent unauthorized access and/... Read more
Kodi 15.0.beta1 - Powerful media center...
Kodi (was XBMC) is an award-winning free and open-source (GPL) software media player and entertainment hub that can be installed on Linux, OS X, Windows, iOS, and Android, featuring a 10-foot user... Read more
DiskCatalogMaker 6.4.12 - Catalog your d...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast. Finder-like intuitive look and feel. Super-fast search algorithm. Can compress catalog data... Read more
Macs Fan Control 1.3.0.0 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
Lyn 1.5.11 - Lightweight image browser a...
Lyn is a lightweight and fast image browser and viewer designed for photographers, graphic artists and Web designers. Featuring an extremely versatile and aesthetically pleasing interface, it... Read more
NeoOffice 2014.11 - Mac-tailored, OpenOf...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
LaunchBar 6.4 - Powerful file/URL/email...
LaunchBar is an award-winning productivity utility that offers an amazingly intuitive and efficient way to search and access any kind of information stored on your computer or on the Web. It provides... Read more
Remotix 3.1.4 - Access all your computer...
Remotix is a fast and powerful application to easily access multiple Macs (and PCs) from your own Mac. Features Complete Apple Screen Sharing support - including Mac OS X login, clipboard... Read more
DesktopLyrics 2.6.6 - Displays current i...
DesktopLyrics is an application that displays the lyrics of the song currently playing in "iTunes" right on your desktop. The lyrics for the song have to be set in iTunes; DesktopLyrics does nothing... Read more
VOX 2.5.1 - Music player that supports m...
VOX is a beautiful music player that supports many filetypes. The beauty is in its simplicity, yet behind the minimal exterior lies a powerful music player with a ton of features and support for all... Read more

This Week at 148Apps: May 18-22, 2015
May Days at 148Apps How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you're looking for. The ones we love become Editor’s Choice, standing out above the... | Read more »
Biz Builder Delux (Games)
Biz Builder Delux 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: Ah, there's nothing like the rhythmic bustle of a burgeoning business burg... especially when you're the one building it... | Read more »
Auroch Digital is Bringing Back Games Wo...
| Read more »
Blades of Brim is a New Endless Runner f...
SYBO Games, the minds behind the ever-popular Subway Surfers, have announced their latest project: Blades of Brim. [Read more] | Read more »
Carbo - Handwriting in the Digital Age...
Carbo - Handwriting in the Digital Age 1.0 Device: iOS Universal Category: Productivity Price: $3.99, Version: 1.0 (iTunes) Description: | Read more »
Draggy Dead (Games)
Draggy Dead 1.1 Device: iOS Universal Category: Games Price: $.99, Version: 1.1 (iTunes) Description: Ditch your dead end job and take up a rewarding career in Grave Robbing today!Guide the recently deceased to a fun filled life of... | Read more »
Bad Dinos (Games)
Bad Dinos 1.0.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.0 (iTunes) Description: | Read more »
The Apple Watch isn't Great as a Fi...
| Read more »
Show the World What You See With Stre.am...
Live broadcasting is getting popular on mobile devices, which is why you can now get Stre.am, by Infinite Takes. [Read more] | Read more »
PhotoTime's 2.1 Update Adds Apple W...
The latest PhotoTime update is adding even more functionality to the handy photo organizing app. Yep, including Apple Watch support. [Read more] | Read more »

Price Scanner via MacPrices.net

12-inch MacBook stock status for Monday, May...
The new 12″ Retina MacBooks are still on backorder at The Apple Store with a 3-5 week waiting period. However, a few models are in stock today at Apple resellers. Stock is limited, so act now if you’... Read more
New 27-inch 3.3GHz 5K iMac in stock with free...
Adorama has the new 27″ 3.3GHz 5K iMac in stock today for $1999 including free shipping plus NY & NJ sales tax only. Adorama will include a free copy of Apple’s 3-year AppleCare Protection Plan. Read more
Memorial Day Weekend Sale: New 27-inch 3.3GHz...
Best Buy has the new 27″ 3.3GHz 5K iMac on sale for $1899.99 this weekend. Choose free shipping or free local store pickup (if available). Sale price for online orders only, in-store prices may vary... Read more
OtterBox Maximizes Portability, Productivity...
From the kitchen recipe book to the boarsroom presentation, the OtterBox Agility Tablet System turns tablets into one of the most versatile pieces of handheld technology available. Available now, the... Read more
Launch of New Car App Gallery and Open Develo...
Automatic, a company on a mission to bring the power of the Internet into every car, has announced the launch of the Automatic App Gallery, an app store for nearly every car or truck on the road... Read more
Memorial Day Weekend Sale: 13-inch 1.6GHz Mac...
Best Buy has the new 13″ 1.6GHz/128GB MacBook Air on sale for $849 on their online store this weekend. Choose free shipping or free local store pickup (if available). Sale price for online orders... Read more
Memorial Day Weekend Sale: 27-inch 3.5GHz 5K...
Best Buy has the 27″ 3.5GHz 5K iMac on sale for $2099.99 this weekend. Choose free shipping or free local store pickup (if available). Sale price for online orders only, in-store prices may vary.... Read more
Sale! 16GB iPad mini 3 for $349, save $50
B&H Photo has the 16GB iPad mini 3 WiFi on sale for $349 including free shipping plus NY sales tax only. Their price is $50 off MSRP, and it’s the lowest price available for this model. Read more
Price drop on 2014 15-inch Retina MacBook Pro...
B&H Photo has dropped prices on 2014 15″ Retina MacBook Pros by $200. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $1799.99 save $200 - 15″ 2.5GHz... Read more
With a Mission to Make Mobile Free, Scratch W...
Scratch Wireless, claiming to be the world’s first truly free mobile service, has announced the availability of a new Scratch-enabled Android smartphone, the Coolpad Arise. The smartphone is equipped... Read more

Jobs Board

Payments Counsel, *Apple* Pay (mobile payme...
**Job Summary** Apple is looking for an atto ey to join Apple 's Legal Department to support Apple Pay. **Key Qualifications** 7+ years of relevant experience Read more
Touch Hardware Design and Integration Enginee...
…Summary** Design, develop, and launch next-generation Touch solutions in the new Apple Watch product category. The Touch team develops cutting-edge Touch solutions and Read more
*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
*Apple* TV Live Streaming Frameworks Test En...
**Job Summary** Work and contribute towards the engineering of Apple 's state-of-the-art products involving video, audio, and graphics in Interactive Media Group (IMG) at Read more
*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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.