TweetFollow Us on Twitter

Sprocket Drag Mgr
Volume Number:11
Issue Number:4
Column Tag:Getting Started

Sprocket and the Drag Manager

Adding an important technology to Sprocket

By Dave Mark, MacTech Magazine Regular Contributing Author

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

This month’s column uses Sprocket to take the Drag Manager out for a quick spin.

I know we were originally scheduled to talk about Sprocket’s menuing model, but we just couldn’t bring everything together in time. We’ll definitely get to it next month.

If you’ve never used the Drag Manager before, bring up the Scrapbook and scroll over to your favorite PICT. Now click on the PICT and drag it out of the Scrapbook window. If you have the Drag Manager installed on your Mac (more on that in a second), you’ll notice a grey rectangle (representing the PICT) following your mouse. Drag the rectangle over any open Finder window. Each time your mouse enters a window, a hilighting rectangle is drawn, telling you that this window is the focus of this drag. If you move the mouse outside the window, the focus rectangle disappears. This focus lets you know which window is to receive the object you are dragging around. If you release the mouse button inside one of your Finder windows (or on the desktop), a clipping file will be created. The clipping file contains the picture you just dragged from the Scrapbook. If you double-click on a clipping file, the Finder displays its contents in a window. If you drag the clipping file around, it acts just like its contents. That is, if you drag a PICT clipping file, it is exactly as if you were dragging the PICT contained in the file. Try it. Drag a Scrapbook PICT onto the desktop, then drag the resulting clipping file back into the Scrapbook.

About the Drag Manager

Under System 7.5 or later, the Drag Manager is built right in. Earlier systems required the installation of the Dragging Enabler extension or its replacement, the Macintosh Drag and Drop extension (version 1.1 is the latest). No matter what System you have, you’ll also need the Clipping Extension if you want the Finder to work with clipping files.

Apple has released a Drag Manager SDK, which contains everything you’ll need to work with the Drag Manager, including some great sample code and two critical DocViewer documents. The first of these, the Drag Manager Programmer’s Guide is basically an Inside Macintosh chapter on the Drag Manager. The second document, Drag and Drop H.I. Guidelines, tells you how the Drag Manager is supposed to look to the user.

If you’ve never worked with the Drag Manager before, there are two excellent articles that will help ease you into the Drag Manager way of thinking. The first of these, was written by Steve Kiene and appears in the June 1994 issue of MacTech Magazine (write to custservice@xplain.com to see if you can order the back issue). The article is called “Macintosh Drag and Drop” and it takes you through the basic Drag Manager concepts and terminology. The second article, “Drag and Drop From the Finder” by Dave Evans and Greg Robbins appeared in the December 1993 issue of develop (issue 16). This article has a slightly different slant than the MacTech article. If you can, read them both before you dive into the Programmer’s Guide. You might also want to check out the article “Implementing Elegant Drag & Drop for Styled Text Fields”, by David Simmons, in the November 1994 issue of MacTech. The article is based on SmallTalk, but is very readable even if you don’t speak the language.

This Month’s Program

This month’s program provides a basic demonstration of the Drag Manager. First, we’ll create a new class called TPictureWindow. A TPictureWindow is a simple, non-growable, non-zoomable, non-scrollable window with a PICT centered in it. The TPictureWindow supports dragging in both directions. That is, you can drag a picture into a TPictureWindow and you can drag a picture from a TPictureWindow as well.

Once our TPictureWindow class is added to our project, we’ll modify our code so that a TPictureWindow is the default document type instead of a TDocWindow. This means that when you select New from the File menu, you’ll create a TPictureWindow instead of a TDocWindow.

Important note: We’ve changed our default Sprocket project from SprocketSample to SprocketStarter. From now on, all of our Sprocket-based programs will start from the latest baseline of SprocketStarter and add the resources, classes, and changes that relate to that month’s topic.

SprocketDragger

This month’s program is based on the files in the folder “SprocketStarter,95.02.01”. In order to distinguish it from the original, I renamed the modified SprocketStarter folder to be “SprocketDragger,95.02.01”. That’s the only reference to SprocketDragger you’ll see. To keep things as clear and as simple as possible, the file names were not changed when I went from SprocketStarter to SprocketDragger. This way, when you want to compare the old and new versions of SetupApplication(), for example, you’ll be comparing two different versions of SprocketStarter.cp.

Both “SprocketStarter,95.02.01” and “SprocketDragger,95.02.01” are based on the Sprocket files found in “Sprocket,95.02.01”. Since Symantec still hasn’t released a product that uses the new Universal Headers, all of this code was built using CodeWarrior CW5.

Building and Running SprocketDragger

Depending on whether you have a PowerMac or not, launch either SprocketStarter.68K.µ or SprocketStarterPPC.µ. You’ll need CodeWarrior CW5 (at least) to build either project. Two likely places where you might run into trouble: the Language and AccessPaths preference panes. Select Preferences from the Edit menu. Scroll to and click on the Access Paths icon. Be sure that an access path leading to your latest Sprocket folder is listed in the User: area (Figure 1).

Figure 1. Be sure a path to your Sprocket folder is added to the User: area.

Next, scroll to and click on the Language icon. Check to be sure that the file listed in the Prefix File field goes with the “.pch++” in your project (Figure 2). For example, if the precompiled header source file SprocketStarterHeadersPPC.pch++ is included in your project, CodeWarrior will build a file called SprocketStarterHeadersPPC. By specifying that file in the Language pane, you are asking CodeWarrior to include that precompiled header in each file it compiles. Why precompile? Since the header is mostly #include files, which likely won’t change during your development cycle, compiling them in advance will definitely speed up your build time. Take a minute to double-click on the “.pch++” file included in your project.

Figure 2. Be sure that the Prefix Header field points to the right
precompiled header for your machine.

By the way, if you get 3 link warnings concerning a possible duplicate ‘ckid’ resource, just ignore them. You’re seeing a CodeWarrior bug that comes up when you include your resource file in the project file. The bug won’t affect program execution.

Once CodeWarrior finishes compiling, it will run SprocketDragger. A splash screen will appear (however briefly) and a picture window will appear (Figure 3). An empty floating window will also appear, but since we don’t use that window, just ignore it. Better yet, can you figure out how to get rid of the floating window entirely? Hint: It is an object of class TToolWindow and it is created in the file SprocketStarter.cp.

Figure 3. The TPictureWindow that appears when SprocketDragger starts up.

The picture window displays the default picture defined by the TPictureWindow class. Basically, this picture appears when a TPictureWindow has not had a PICT dragged to it yet. With SprocketDragger still running, go to the Finder and drag an icon from the Finder onto the TPictureWindow. The TPictureWindow does not react to a non-PICT drag.

Now bring up the Scrapbook and drag a picture from the Scrapbook onto the picture window. This time, a highlighting rectangle appears around the border of the window, indicating that the window is willing to accept this data. If you release the drag inside the picture window, the picture you just dragged will appear in the window.

If you have the Clipping extension installed, try dragging the picture in the picture window into a Finder window. My favorite is to drag from the picture window into the trash. No matter what Finder window you select, a clipping file will appear containing the dragged PICT. Try dragging an image from the Scrapbook to the desktop to create a clipping file, then drag the clipping file onto the picture window. Once again, the highlighting rectangle appears in the picture window as the focus of your drag enters the window. This indicates that the picture window is accepting the drag. And why not, since the clipping file looks just like a PICT to the picture window.

Try dragging a picture from the picture window into a window that can’t receive a drag. For example, try running Microsoft Word or any other non-drag-friendly application and drag from the picture window into the Word window. When you release the mouse, the dragging outline will zoom back to the original window, indicating that the drag was rejected.

Next, select New from the File menu to create a second picture window. When the window appears, drag it to the side so you can see both picture windows at the same time. Notice that the windows are numbered so you can tell them apart. Assuming you now have a different picture in each window, try dragging from one window to the other.

There are a lot of other ways you can test out your new dragging environment. For now, though, let’s get into the resources and source code that makes this all possible.

SprocketDragger Resources

SprocketDragger added two new resources to the file SprocketStarter.rsrc. A PICT with a resource ID of 1025 was added to give us a default picture to display in windows that hadn’t received a drag yet. A WIND with a resource ID of 1028 acted as a template for the TPictureWindow window.

Modify SprocketStarter.cp

The first source code change I made was in the file SprocketStarter.cp. I modified the routine CreateNewDocument() to create a TPictureWindow instead of a TDocWindow:

OSErr
CreateNewDocument(void)
 {
 TPictureWindow  *aNewWindow = new TPictureWindow();
 
 if (aNewWindow)
 return noErr;
 else
 return memFullErr;
 }

Remember, Sprocket calls CreateNewDocument() whenever an ‘oapp’ Apple event is received or when New is selected from the File menu. Since we haven’t gotten into Sprocket’s menu model yet, we didn’t implement a separate, TPictureWindow test menu.

Add the TPictureWindow Class

Once those changes were made, the only other thing left to do was to create the TPictureWindow class and add it to the project. As you’d expect, the TPictureWindow class was implemented in the files PictureWindow.cp and PictureWindow.h. As we go through the source code in these two files, you’ll see how we took advantage of the Drag Manager code already built into Sprocket.

PictureWindow.h

PictureWindow.h starts off in the usual way, by defining a constant to prevent an infinite include loop and by including the declarations associated with its base class, TWindow.

#ifndef _PICTUREWINDOW_
#define _PICTUREWINDOW_

#ifndef _WINDOW_
#include"Window.h"
#endif

The TWindow class implements all the basic features that make up a general window object. The TDocWindow class (the one with the spinning cursor which we worked with last month) is based on the TWindow class. The TPictureWindow class borrows heavily from the design of the TDocWindow class and is also based on the TWindow class.

class TPictureWindow : public TWindow
{
  public:
 TPictureWindow();
 virtual  ~TPictureWindow();

 virtual WindowPtr MakeNewWindow( WindowPtr behindWindow );

 virtual void    Draw(void);
 
 virtual void    ClickAndDrag( EventRecord *eventPtr );
 
 virtualOSErr    DragEnterWindow( DragReference dragRef );
 virtualOSErr    DragInWindow( DragReference dragRef );
 virtualOSErr    DragLeaveWindow( DragReference dragRef );
 virtualOSErr    HandleDrop( DragReference dragRef );
 
// Non-TWindow methods...
 virtual PicHandle LoadDefaultPicture();
 virtual void    CenterPict( PicHandle picture, 
 Rect *destRectPtr );
 virtual Boolean IsPictFlavorAvailable( 
 DragReference dragRef );
 virtual Boolean IsMouseInContentRgn( 
 DragReference dragRef );

The TPictureWindow class uses 4 data members. fgWindowTitleCount is a static member, which means that a single unsigned long is shared among all TPictureWindow objects. fgWindowTitleCount is incremented every time you create a new TPictureWindow and provides the number you see in the TPictureWindow title bar.

protected:
 static unsigned longfgWindowTitleCount;

fCanAcceptDrag gets set to true if the current drag contains data that is acceptable to the TPictureWindow (in other words, PICT data). fDraggedPicHandle starts off as nil but points to a PICT if one is dragged into the window. fIsWindowHighlighted is true if the window’s drag highlighting is currently turned on.

 BooleanfCanAcceptDrag;
 PicHandlefDraggedPicHandle;
 BooleanfIsWindowHighlighted;
};

#endif

PictureWindow.cp

PictureWindow.cp starts off with a pair of constants that define the resource IDs for the WIND template and the default PICT.

const short kPictureWindowTemplateID = 1028;
const short kDefaultPICTResID = 1025;

“PictureWindow.h” contains the TPictureWindow class declaration. <ToolUtils.h> contains the declaration of the routines NumToString() and GetPicture().

#include "PictureWindow.h"
#include <ToolUtils.h>

Before we get into the TPictureWindow methods, we’ll initialize the static that tracks the index used in the window titles. We can’t initialize the static inside a method, becuase the initialization would be redone every time a new TPictureWindow was created (or the initializing method got called).

unsigned long    TPictureWindow::fgWindowTitleCount = 0;

The TPictureWindow constructor first initializes fDraggedPicHandle (since we don’t have a dragged-in picture yet). It then bumps fgWindowTitleCount so our first window starts with the number 1 instead of 0. Finally, it calls the inherited CreateWindow() to create a new window. CreateWindow() belongs to the TWindow class and calls the MakeNewWindow() method, which we have overridden (ours is right below the destructor).

TPictureWindow::TPictureWindow()
{
 fDraggedPicHandle = nil;

 TPictureWindow::fgWindowTitleCount++;
 this->CreateWindow();
}

The destructor doesn’t do anything. If we intended SprocketDragger to be a “real” application, we’d free up the memory allocated to any received picture, assuming fDraggedPicHandle was not nil.

TPictureWindow::~TPictureWindow()
{
}

MakeNewWindow() creates a new window based on our picture window WIND template. Basically, this method was lifted from the TDocWindow class.

WindowPtr
TPictureWindow::MakeNewWindow( WindowPtr behindWindow )
{
 WindowPtraWindow;
 Str255 titleString;
 GrafPtrsavedPort;
 
 GetPort(&savedPort);
 
 aWindow = GetNewColorOrBlackAndWhiteWindow( 
 kPictureWindowTemplateID,
 nil, behindWindow );
 
 if (aWindow)
 {
 GetWTitle(aWindow,titleString);
 if (StrLength(titleString) != 0)
 {
 Str255 numberString;
 
 NumToString( fgWindowTitleCount, numberString );
 BlockMove(&numberString[1],&titleString[titleString[0]+1],
 numberString[0]);
 titleString[0] += numberString[0];
 }
 SetWTitle(aWindow,titleString);

 SetPort(aWindow);

 ShowWindow(aWindow);
 }
 SetPort(savedPort);

 return aWindow;
}

The Draw method gets called in response to an update event. Draw() checks to see if we have a dragged in PICT. If so, we draw it, otherwise we draw the default picture. CenterPict() is an old centering routine I stole from volume I of the Primer.

void
TPictureWindow::Draw(void)
{
 PicHandlepic;
 Rect   r;
 
 r = fWindow->portRect;
 EraseRect( &r );
 
 if ( fDraggedPicHandle == nil )
 pic = this->LoadDefaultPicture();
 else
 pic = fDraggedPicHandle;

 this->CenterPict( pic, &r );
 DrawPicture( pic, &r );
}

ClickAndDrag() gets called when a click occurs in the window’s content region and is immediately followed by a drag. This means that the user is trying to drag a picture from our window. The drag might go outside our application, to another part of our application, or even to another part of our window. We’ll start a new drag by calling NewDrag().

void
TPictureWindow::ClickAndDrag( EventRecord *eventPtr )
{
 OSErr  err;
 DragReference   dragRef;
 RgnHandledragRegion, tempRgn;
 Rect   itemBounds;
 Handle flavorDataHandle;
    
    err = NewDrag( &dragRef );
    if ( err != noErr )
 return;

 if ( fDraggedPicHandle == nil )
 flavorDataHandle = (Handle)this->LoadDefaultPicture();
 else
 flavorDataHandle = (Handle)fDraggedPicHandle;

 HLock( flavorDataHandle );

We’ll then tell the Drag Manager that this drag contains PICT data. Think of flavors as types, such as those found in the scrap. The second parameter is a serial number we want to assign to this item. We’ll use the WindowPtr as a serial number, though we could have used the number 1L or even 599923L. When you get into drags containing multiple items, this becomes more of an issue.

 err = AddDragItemFlavor( dragRef,
                    (ItemReference)fWindow,
                    (FlavorType) 'PICT',
                    (Ptr)*flavorDataHandle,
                    GetHandleSize((Handle)flavorDataHandle ),
                    (FlavorFlags)0 );

We locked the PicHandle so we could use its master pointer. Once we return from AddDragItemFlavor(), we unlock the handle.

 HUnlock( flavorDataHandle );

If we encounter a problem, we’ll dispose of the drag and return.

    if ( err != noErr )
 {
 DisposeDrag( dragRef );
 return;
 }

Next, we’ll calculate the rectangle we want dragged out of the window. This rectangle has nothing to do with the data we are sending, but just defines the xor rectangle that represents the drag. Try modifying the drag so the dragged rectangle represents the PICT’s frame instead. Next, change the drag so it drags the true outline of the picture around instead of just its framing rectangle. Hint: check out the routine BitMapToRegion().

 itemBounds = (**((WindowPeek)fWindow)->contRgn).rgnBBox;
 
 err = SetDragItemBounds( dragRef, (ItemReference)fWindow, 
 &itemBounds );
 if ( err != noErr )
 {
 DisposeDrag( dragRef );
 return;
 }

This code takes a solid region and turns it into just the frame of the region. We then pass the rectangular region on to TrackDrag() which drags the rectangle around.

 dragRegion = NewRgn();
 RectRgn( dragRegion, &itemBounds );
 tempRgn = NewRgn();
 CopyRgn( dragRegion, tempRgn );
 InsetRgn( tempRgn, 1, 1 );
 DiffRgn( dragRegion, tempRgn, dragRegion );
 DisposeRgn( tempRgn );
 
 err = TrackDrag( dragRef, eventPtr, dragRegion );
 DisposeRgn( dragRegion );
 DisposeDrag( dragRef );
 return;
}

DragEnterWindow() gets called when the window receives a dragEnterWindow message, indicating that a drag is entering our window. The sender of the drag might be our window, our application, or a different application (like the Finder). We’ll first check to see if the incoming drag has PICT data and set fCanAcceptDrag accordingly. We’ll also set fIsWindowHighlighted to false, since we haven’t done any highlighting yet.

OSErr
TPictureWindow::DragEnterWindow( DragReference dragRef )
{
 fCanAcceptDrag = IsPictFlavorAvailable( dragRef );
 fIsWindowHighlighted = false;
 
 if ( fCanAcceptDrag )
 return noErr;
 else
 return dragNotAcceptedErr;
}

DragInWindow() gets called when the window receives a dragInWindow message. We’ll receive one dragEnterWindow, many dragInWindows, then one dragLeaveWindow messages each time a drag enters our window.

OSErr
TPictureWindow::DragInWindow( DragReference dragRef )
{
 DragAttributes  attributes;
 RgnHandletempRgn;

GetDragAttributes() gives us access to the dragHasLeftSenderWindow and dragInsideSenderWindow flags, which tell us if the drag ever left its originating window and if the drag is currently inside the sending window. Since we don’t want a window to receive a drag from itself (from another window in the same application is fine, though) we’ll return if the sender is us.

 GetDragAttributes( dragRef, &attributes );
 
 if ( (! fCanAcceptDrag) || (! (attributes & 
 dragHasLeftSenderWindow)) 
 || (attributes & dragInsideSenderWindow) )
 return dragNotAcceptedErr;

If the mouse is in our content region (as opposed to in our title bar - important difference!) we’ll highlight the window if it isn’t already highlighted.

 if ( this->IsMouseInContentRgn( dragRef ) )
 {
 if ( ! fIsWindowHighlighted )
 {
 tempRgn = NewRgn();
 RectRgn( tempRgn, &fWindow->portRect );
 
 if ( ShowDragHilite( dragRef, tempRgn, true ) == noErr)
 fIsWindowHighlighted = true;
 
 DisposeRgn(tempRgn);
 }
 }
 
 return noErr;
}

Finally, once the drag focus leaves our window, we’ll hide the highlighting and reset fIsWindowHighlighted and fCanAcceptDrag (just to be safe).

OSErr
TPictureWindow::DragLeaveWindow( DragReference dragRef )
{
 if ( fIsWindowHighlighted )
 HideDragHilite( dragRef );
 
 fIsWindowHighlighted = false;
 fCanAcceptDrag = false;
 
 return noErr;
}

HandleDrop() gets called when our window has accepted a drag and we are now supposed to save the data.

OSErr
TPictureWindow::HandleDrop( DragReference dragRef )
{
 OSErr  err;
 Size   dataSize;
 ItemReference   item;
 FlavorFlagsflags;
 DragAttributes  attributes;

 GetDragAttributes( dragRef, &attributes );
 
 if ( attributes & dragInsideSenderWindow )
 return dragNotAcceptedErr;

We’ll first make sure the first drag item has PICT data. If it does, we’ll get the data size, then create a new handle to store the new PICT. Notice that we first try to allocate memory using TempNewHandle() which gets its data from outside the application heap. If that fails, we’ll go the more normal route of calling NewHandle(). This isn’t necessarily the right way to do this, since we are stealing memory from other applications, but I thought you might want to play with this call.

 err = GetDragItemReferenceNumber( dragRef, 1, &item );
 if ( err == noErr )
 err = GetFlavorFlags( dragRef, item, 'PICT', &flags );

 if ( err == noErr )
 {
 err = GetFlavorDataSize( dragRef, item, 'PICT', &dataSize);
 if  (err == noErr )
 {
 fDraggedPicHandle = (PicHandle)TempNewHandle( dataSize, 
 &err );
 
 if ( fDraggedPicHandle == nil )
 fDraggedPicHandle = (PicHandle)NewHandle( dataSize );

If the memory was successfully allocated, we’ll load the data from the drag using GetFlavorData() then force a redraw assuming we got the data OK.

 if ( fDraggedPicHandle == nil )
 err = dragNotAcceptedErr;
 else
 {
 HLock( (Handle)fDraggedPicHandle );
 err = GetFlavorData( dragRef, item, 'PICT',
 *fDraggedPicHandle, &dataSize, 0L );
 HUnlock( (Handle)fDraggedPicHandle );

 if ( err != noErr)
 {
 err = dragNotAcceptedErr;
 DisposeHandle( (Handle)fDraggedPicHandle );
 fDraggedPicHandle = nil;
 }
 else
 {
 SetPort( fWindow );
 InvalRect( &(fWindow->portRect) );
 }
 }
 }
 }
 
 return( err );
}

LoadDefaultPicture() loads the PICT resource and drops into the debugger if the PICT resource is missing.

PicHandle
TPictureWindow::LoadDefaultPicture()
{
 PicHandlepic;
 
 pic = GetPicture( kDefaultPICTResID );
 
 if ( pic == nil )
 {
 DebugStr( (StringPtr) "\pCould not load PICT resource!" );
 return (PicHandle)nil;
 }
 else
 return( pic );
}

CenterPict() takes a PicHandle and a Rect as parameters. On input, the Rect contains the window’s portRect, that is, the rectangle the picture should be centered in. On output, the Rect contains a rectangle the size of the picture, but centered in the window and in the window’s local coordinate system..

void
TPictureWindow::CenterPict( PicHandle picture, Rect *destRectPtr )
{
 Rect windRect, pictRect;
 
 windRect = *destRectPtr;
 pictRect = (**( picture )).picFrame;
 OffsetRect( &pictRect, windRect.left - pictRect.left,
    windRect.top  - pictRect.top);
 OffsetRect( &pictRect,(windRect.right - pictRect.right)/2,
   (windRect.bottom - pictRect.bottom)/2);
 *destRectPtr = pictRect;
}

IsPictFlavorAvailable() returns true if the first item in the specified drag contains a PICT flavor.

Boolean
TPictureWindow::IsPictFlavorAvailable( DragReference dragRef )
{
 unsigned short  numItems;
 FlavorFlagsflags;
 OSErr  err;
 ItemReference   item;

We’ll call CountDragItems() to find out how many items are in the drag.

 CountDragItems( dragRef, &numItems );
 
 if ( numItems < 1 )
 return( false );

We call GetDragItemReferenceNumber() to retrieve the item reference number of the first item. We’ll pass that item reference number to GetFlavorFlags() to see if the item has a PICT flavor.

 err = GetDragItemReferenceNumber( dragRef, 1, &item );
 if ( err == noErr )
 err = GetFlavorFlags( dragRef, item, 'PICT', &flags );
 
 return( err == noErr );
}

IsMouseInContentRgn() returns true if the mouse is in the content region of the window. This is important because we don’t want to react to a drag into the title bar of our window. We only react to drags actually inside the window’s content region.

Boolean
TPictureWindow::IsMouseInContentRgn( DragReference dragRef )
{
 Point  globalMouse;
 OSErr  err;
 
 err = GetDragMouse( dragRef, &globalMouse, 0L );
 
 if ( err == noErr )
 return( PtInRgn( globalMouse, ((WindowPeek)fWindow)->contRgn
             ) );
 else
 return( false );
}

Till Next Month

I really wish I could have had about twice as much space in this month’s column. There is a lot more to the Drag Manager than what I was able to get into here, but this should get you started. The Drag Manager is extremely important. You should definitely support it in all of your applications. A universally available drag and drop capability will help distinguish future Macintosh applications and environments from Windows 95. Though Apple has recently introduced a number of important new technologies (OSA being a prime example), there are none that affect the user’s experience as directly as the Drag Manager. In the near future, applications that support the Drag Manager will feel “normal” and those that don’t will feel old-fashioned and clunky. The user will expect Drag and Drop support and will likely be pretty unforgiving if it is absent.

OK, stepping off my soapbox now. Next month, we’ll take a look at Sprocket’s menu handling model. As I said at the end of last month’s column, Sprocket handles menus in much the same way as OpenDoc, so if you learn how to handle menus in Sprocket, you’ll have a leg up when you start writing your first OpenDoc part.

 
AAPL
$99.02
Apple Inc.
+1.35
MSFT
$43.97
Microsoft Corpora
-0.53
GOOG
$590.60
Google Inc.
+1.58

MacTech Search:
Community Search:

Software Updates via MacUpdate

OS X Yosemite Wallpaper 1.0 - Desktop im...
OS X Yosemite Wallpaper is the gorgeous new background image for Apple's upcoming OS X 10.10 Yosemite. This wallpaper is available for all screen resolutions with a source file that measures 5,418... Read more
Acorn 4.4 - Bitmap image editor. (Demo)
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Bartender 1.2.20 - Organize your menu ba...
Bartender lets you organize your menu bar apps. Features: Lets you tidy your menu bar apps how you want. See your menu bar apps when you want. Hide the apps you need to run, but do not need to... Read more
TotalFinder 1.6.2 - Adds tabs, hotkeys,...
TotalFinder is a universally acclaimed navigational companion for your Mac. Enhance your Mac's Finder with features so smart and convenient, you won't believe you ever lived without them. Tab-based... Read more
Vienna 3.0.0 RC 2 :be5265e: - RSS and At...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
VLC Media Player 2.1.5 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Default Folder X 4.6.7 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more
TinkerTool 5.3 - Expanded preference set...
TinkerTool is an application that gives you access to additional preference settings Apple has built into Mac OS X. This allows to activate hidden features in the operating system and in some of the... Read more
Audio Hijack Pro 2.11.0 - Record and enh...
Audio Hijack Pro drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio with Audio Hijack... Read more
Intermission 1.1.1 - Pause and rewind li...
Intermission allows you to pause and rewind live audio from any application on your Mac. Intermission will buffer up to 3 hours of audio, allowing users to skip through any assortment of audio... Read more

Latest Forum Discussions

See All

Traps n’ Gemstones Review
Traps n’ Gemstones Review By Campbell Bird on July 28th, 2014 Our Rating: :: CASTLEVANIA JONESUniversal App - Designed for iPhone and iPad Fight mummies, dig tunnels, and ride a runaway minecart to discover ancient secrets in this... | Read more »
The Phantom PI Mission Apparition Review
The Phantom PI Mission Apparition Review By Jordan Minor on July 28th, 2014 Our Rating: :: GHOSTS BUSTEDUniversal App - Designed for iPhone and iPad The Phantom PI is an exceedingly clever and well-crafted adventure game.   | Read more »
More Stubies Are Coming Your Way in a Ne...
More Stubies Are Coming Your Way in a New Update Posted by Jessica Fisher on July 28th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
The Great Prank War Review
The Great Prank War Review By Nadia Oxford on July 28th, 2014 Our Rating: :: PRANKING IS SERIOUS BUSINESSUniversal App - Designed for iPhone and iPad Though short, The Great Prank War offers an interesting and fun mix of action and... | Read more »
Marvel Contest of Champions Announced at...
Marvel Contest of Champions Announced at Comic-Con Posted by Jennifer Allen on July 28th, 2014 [ permalink ] Announced over the weekend at San Diego Comic-Con was the fairly exciting looking Marvel Contest of Champions. | Read more »
Teenage Mutant Ninja Turtles Review
Teenage Mutant Ninja Turtles Review By Jennifer Allen on July 28th, 2014 Our Rating: :: DULL SWIPINGUniversal App - Designed for iPhone and iPad The pizza power is weak when it comes to this Teenage Mutant Ninja Turtles game.   | Read more »
Exploration Focused Puzzle Game Beatbudd...
Exploration Focused Puzzle Game Beatbuddy Set to Make Transition from PC to iOS this September Posted by Jennifer Allen on July 28th, 2014 [ permalink ] | Read more »
PlanetHD
PlanetHD By Nadia Oxford on July 28th, 2014 Our Rating: :: SPACE MADNESSUniversal App - Designed for iPhone and iPad PlanetHD will keep players busy for a while, though its unpredictable physics are a handful to deal with.   | Read more »
This Week at 148Apps: July 21-25, 2014
Another Week of Expert App Reviews   At 148Apps, we help you sort through the great ocean of apps to find the ones we think you’ll like and the ones you’ll need. Our top picks become Editor’s Choice, our stamp of approval for apps with that little... | Read more »
Reddme for iPhone - The Reddit Client (...
Reddme for iPhone - The Reddit Client 1.0 Device: iOS iPhone Category: News Price: $.99, Version: 1.0 (iTunes) Description: Reddme for iPhone is an iOS 7-optimized Reddit client that offers a refreshing new way to experience Reddit... | Read more »

Price Scanner via MacPrices.net

13-inch 2.5GHz MacBook Pro on sale for $1099,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $1099.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $100 off MSRP. Price is... Read more
Roundup of Apple refurbished MacBook Pros, th...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available for up to $400 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. Their prices... Read more
Record Mac Shipments In Q2/14 Confound Analys...
A Seeking Alpha Trefis commentary notes that Apple’s fiscal Q3 2014 results released July 22, beat market predictions on earnings, although revenues were slightly lower than anticipated. Apple’s Mac’... Read more
Intel To Launch Core M Silicon For Use In Not...
Digitimes’ Monica Chen and Joseph Tsai, report that Intel will launch 14nm-based Core M series processors specifically for use in fanless notebook/tablet 2-in-1 models in Q4 2014, with many models to... Read more
Apple’s 2014 Back to School promotion: $100 g...
 Apple’s 2014 Back to School promotion includes a free $100 App Store Gift Card with the purchase of any new Mac (Mac mini excluded), or a $50 Gift Card with the purchase of an iPad or iPhone,... Read more
iMacs on sale for $150 off MSRP, $250 off for...
Best Buy has iMacs on sale for up to $160 off MSRP for a limited time. Choose free home shipping or free instant local store pickup (if available). Prices are valid for online orders only, in-store... Read more
Mac minis on sale for $100 off MSRP, starting...
Best Buy has Mac minis on sale for $100 off MSRP. Choose free shipping or free instant local store pickup. Prices are for online orders only, in-store prices may vary: 2.5GHz Mac mini: $499.99 2.3GHz... Read more
Global Tablet Market Grows 11% in Q2/14 Notwi...
Worldwide tablet sales grew 11.0 percent year over year in the second quarter of 2014, with shipments reaching 49.3 million units according to preliminary data from the International Data Corporation... Read more
New iPhone 6 Models to Have Staggered Release...
Digitimes’ Cage Chao and Steve Shen report that according to unnamed sources in Apple’s upstream iPhone supply chain, the new 5.5-inch iPhone will be released several months later than the new 4.7-... Read more
New iOS App Helps People Feel Good About thei...
Mobile shoppers looking for big savings at their favorite stores can turn to the Goodshop app, a new iOS app with the latest coupons and deals at more than 5,000 online stores. In addition to being a... Read more

Jobs Board

Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.