TweetFollow Us on Twitter

TearOff TCL
Volume Number:9
Issue Number:2
Column Tag:TCL Workshop

Related Info: Menu Manager Window Manager

TCL Knick Knacks

The compiler knows!!

By John A. Love, III, MacTutor Regular Contributing Author

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

About the author

John is a member of the Washington Apple Pi Users’ Group from the greater Washington D.C. metropolitan area and can be reached on America Online{John Love} and on GEnie {J.LOVE7}.

This series

The purpose of this continuing series is to laboriously trace through the source code of Symantec’s THINK Class Library (TCL) that serves as the Object Oriented Programming (OOP) arm for their Pascal and C compilers to provide the answers to the age-old question, “Who does what to whom?”.

Forrest Tanaka and Sandy Mossberg wake up, this one’s for you!!!

This article ...

In the first of my “TCL Knick-Knacks” series which appeared in last August’s issue, I promised an article that addressed Tear-Off Menus (TOM), and since a promise is a promise ...

Remember that great article by Don Melton and Mike Ritter that appeared in MacTutor way, way back in April, 1988? Truly a rosy masterpiece that addressed “Tear-Off Menus & Palettes”. However, I recall all the frustration that I encountered in understanding the thorny “Why all this blasted overhead just to handle a window, even a menu-type window?” Well the folks at Symantec have successfully removed the absolute necessity of having to understand all the thorny details.

In my particular implementation, a Tear-Off Menu is both a floating window and a floating palette with each pane in this palette functionally equivalent to an individual Menu item. First, I will stipulate all a programmer must do to implement my variety of Tear-Off Menus using the TCL and then I will amplify on each step.

All this code is included on MacTutor’s disk from last August’s issue. It is also included in my “Feature Flick” package which addresses QuickTime™ and introduces my new class = CQuickTime. You can find the latter on America Online.

First, what to do ...

1) include a 'WDEF' or Window Definition Procedure in the resource file.

2) include a 'MDEF' or Menu Definition Procedure in the resource file.

3) create a 'MENU' for your Tear-Off Menu with the same ID as the 'MDEF' and then place this ID in your 'MBAR' resource.

4) create a 'WIND' resource whose ID also equals that of the 'MDEF'. For the sake of consistency, I make the IDs of the 'MDEF', 'MENU' and 'WIND' all match. Using this approach, it ’s much easier to keep things straight when you have more than one Tear-Off Menu .

5) sub-class TCL’s CGridSelector. CGridSelector is a CSelector is a CPanorama is a CPane and is functionally a palette or array of grid elements wherein each Menu item of your Tear-Off Menu is a distinct pane or grid element of this CGridSelector.

/* 1 */
struct  CCustomSelector : CGridSelector
{
void    DrawItem (short theItem, Rect *theBox);
// Inherited from CSelector:
void    DoClick (Point hitPt, short modifierKeys, long when);
};

At a minimum, override CGridSelector’s DrawItem for drawing. Optionally, override DoClick which CGridSelector inherits from CSelector for selection. Drawing occurs when you pull down the menu from the main menubar or in response to updates after your menu has been torn-off. DoClick comes into play when you click on one of the grid items or panes of your already torn-off menu.

6) sub-class TCL’s CTearOffMenu. CTearOffMenu is a CDirector. As I “panefully” described last August, “a director is a bureaucrat that supervises a window”. So, instead of a CDocument supervising our window, our CTearOffMenu does the supervising.

/* 2 */
struct CTearMenuDir : CTearOffMenu 
{
 void   ITearMenuDir (CApplication *aSupervisor);
 void   DoCommand (long theCommand);
 void   CloseWind (CWindow *theWindow);
};

At a minimum, override CTearOffMenu’s ITearOffMenu (I call it ITearMenuDir). Within ITearMenuDir, call ITearOffMenu, inherited from the superclass, to create your floating window. Then create and initialize your CGridSelector. The new CGridSelector serves as the main CPane of the CTearOffMenu; as a matter of fact, the created CGridSelector is stuffed into CTearOffMenu::itsPane. IGridSelector sets up the Menu Command Number Base for the array of grid items or Menu items; given this base #, the Command Number for each grid/Menu item is separated from its predecessor by one. You also pass to IGridSelector the number of rows & colums in this array or matrix of Menu items. For a conventional Menu there is obviously only one column, however, for a graphic Palette such as the Pattern Menu in MacPaint™, there are multiple columns.

After you call IGridSelector and do some more housekeeping, create and initialize a CSelectorMDEF object. ISelectorMDEF calls IPaneMDEF which calls IMenuDefProc to fill in your 'MDEF' resource stub. Given this filling in, when the Menu Manager calls _MenuSelect, for example, your 'MDEF' is called to magically draw the Menu and choose a particular Menu item.

You pass the above-mentioned CGridSelector object (= CPane) to ISelectorMDEF which, in turn, passes the same object into IPaneMDEF for storage in CPaneMDEF::itsPane. As a direct result, CTearOffMenu::itsPane = CPaneMDEF::itsPane = the new CGridSelector. This is a key point, so hold this thought

I do not use DoCommand, inherited from CTearOffMenu’s superclass = CDirector, in my simple example. I refer you to the “Art Class” example provided by Symantec on their TCL disk(s) wherein DoCommand is overidden.

I’ll reveal later why I override CTearOffMenu::CloseWindow.

7) Within your CMovieApp:

/* 3 */

struct CMovieApp : CApplication
{
 // One instance variable:
 CTearMenuDir  *itsTearMenu;

 // So we have floating windows:
 void   MakeDesktop (void);

 // etc.
 void   SetUpMenus (void);

 void   SwitchToDA (void); 
 void   SwitchFromDA (void); 

 void   DoCommand (long theCommand);
 void   DoKeyDown (char theChar, Byte keyCode, EventRecord *macEvent);

}; /* CMovieApp */

a) place a reference to your CTearOffMenu in an instance variable, said reference being created within CMovieApp::SetUpMenus. This is optional; however, as shown later, I need this reference in my CMovieApp::DoKeyDown.

b) override CApplication::MakeDesktop in order to place a new(CFWDesktop) into the global = gDesktop. In this manner, the desktop will support floating windows properly.

c) override CApplication::SetUpMenus. I will address this in detail later.

d) override CApplications’s SwitchToDA and SwitchFromDA to disable and enable, respectively, your Tear-Off Menu(s). These paired Switch routines are typically the place for disabling and enabling whole Menus only, whereas your UpdateMenus method(s) can disable/enable either whole Menus or individual Menu items:

/* 4 */

 void CMovieApp::SwitchToDA (void)
 {
 gBartender-> DisableMenu(kTearMenu);

 inherited::SwitchToDA();
 } /* SwitchToDA */

 void CMovieApp::SwitchFromDA (void)
 {
 gBartender->EnableMenu(kTearMenu);

 inherited::SwitchFromDA();
 } /* SwitchFromDA */

e) override CApplication::DoCommand to respond to the selection of a discrete pane or Menu item of your CGridSelector palette. This response occurs when you either pull down your Menu to select one of the items as if it were an ordinary Menu or tear it off and subsequently click on the content portion of the torn-off Menu’s floating window.

f) override CApplication::DoKeyDown to response to <CMD> key shortcut selections of the various grid elements within your palette. I don’t have any <CMD> key shortcuts, but I allow the user to use <CMD-Tab> to alternately show or hide the torn-off Menu {HyperCard™, anyone?}.

Next, the details ...

Above, I grouped all the resource stuff together and ditto for the Tear-Off classes and CMovieApp modifications. For the purposes of introduction, these groupings serve well. However, when it now comes time to “follow the bouncing ball”, I am going to be bouncing from group-to-group, mixing it up so-to-speak. I believe this is mandatory in order to logically follow all the interactions as well as the reasons behind them.

The window

Here’s a portion of my “movies.r” that SARez™ chews on:

/* 5 */

// Special WDEF for Floating Windows:
include "Windoid";
#define kWindoid 104

// Apple reserves 0 -> 127:
#define kTearMenu1000

resource'WIND' (kTearMenu, "1st Floating Tearoff Menu",
 purgeable)
{
{40,  40, 110, 112},
// = 16*kWindoid + noGrowDocProc:
1668,
invisible,
goAway,
0x0,
"",
/* I define SystemSevenOrLater
** (found in "Types.r") = true
** in my "movies.r" file:    */
noAutoCenter
};

Note in the above 'WIND' resource description that the defProc field implements the arithmetic mandated by the Window Manager, namely, 16*the ID of the 'WDEF' resource + the window variant. In this manner, the Window Manager uses my 'WDEF' for drawing the window. Take a long stare at the shape and appearance of MacPaint’s tear-off Palette, especially that of its title bar. That is the 'WDEF' that is the sole occupant of the TCL file = “Windoid” that Symantec passes along with their TCL package, together with its source code, natch.

When the TCL initializes your Tear-Off Menu object (my ITearMenuDir calls TCL’s ITearOffMenu), the ID of your 'WIND' resource is passed to inherited::ITearOffMenu as a parameter. The latter calls:

/* 6 */

// CDirector::itsWindow
itsWindow = new (CWindow);
itsWindow->IWindow(WINDid,
 TRUE,  /* floating */
 gDesktop,
 this /* supervisor */);

So a window is created and we’re off and running. Remember, this = the object that was sent the message = ITearOffMenu. Therefore, the supervisor of the floating window becomes the CDirector = my CTearMenuDir, a sub-class of CTearOffMenu. As you will see shortly, this initialization takes place below within CMovieApp::SetUpMenus but cool it.

Next, we’ve got to make the TCL handle our Tear-Off Menu properly, and since the latter is a floating window:

/* 7 */

void  CMovieApp::MakeDesktop (void)
{
 gDesktop = new (CFWDesktop);
 ((CFWDesktop*)gDesktop)-> IFWDesktop(this);
}/* MakeDesktop */

Therefore, the window’s enclosure = gDesktop passed to IWindow above is a CFWDesktop, so everything’s right with the world. Speaking of floating windows, there is a popular, but erroneous, conception that all floating windows must disappear when your application is suspended. Apple’s Human Interface Guidelines stipulate that this be true for Tear-Off Menus; they make no such statement for all floating windows, leaving the programmer the option to do his/her own thing for other floating windows. The mandatory disappearance of floating Menus is logical since MultiFinder™ has switched out your Menus a floating Menu for a non-existent Menu ??? get a life!!! The TCL implements the Human Interface Guidelines precisely within CTearOffMenu’s Suspend and Resume methods.

The Menu

When the Menu Manager is called, e.g., _MenuSelect, the Menu’s 'MDEF' is called via something akin to:

;8

 clr.l    -(sp)
 push.w   #ID
 _GetMenu
 move.l   (sp)+, a0  ; = MenuHandle
 move.l   (a0), a1
 ; menuDefProc is filled in by
 ; _GetMenu after it loads the
 ; 'MENU' resource.  This field
 ; then contains a Handle to my
 ; 'MDEF' because I place the
 ; latter's ID in the 'MENU':
 push.w   theMessage
 push.l   a0
 ; push additional parms here
 ; depending on the Message:
 move.l   menuDefProc(a1),a1
 move.l   (a1),a1
 jmp      (a1)

The TCL implements a similar methodology. Before I give all the gory details of this methodology, first let me present what the 'MDEF' and 'MENU' resources look like:

/* 9 */

// more on this buzzard later:
typedef struct   GenericMDEFRec {
short   JMPinstruction;
VoidFuncdefProc;
CMenuDefProc*itsMenuDefProc;
}GenericMDEFRec,
 *GenericMDEFPtr,
 **GenericMDEFHand;

#define kMDEF  kTearMenu

/* Only this stub appears
** in your .rsrc file:    */
data  'MDEF'(kMDEF, "1st Floating Tearoff Menu", purgeable)
{
$"4EF9" // “jmp”
$"00000000" // “defProc”
$"00000000" // “itsMenuDefProc”
};

The above jmp (a1) effectively jumps to the address containing 4EF900000000, thus in turn executing another jump to the address contained in the next four bytes represented here by zeros. We’ll see below that after ITearOffMenu creates your floating window it calls CMenuDefProc::IMenuDefProc and that these zeros will be filled in by IMenuDefProc with the effective address of TCL’s GenericMDEF. The latter is a generic Menu Definition Procedure which uses Object C. It receives a mDrawMsg to draw the Menu, a mChooseMsg to handle selection from the Menu, a mSizeMsg to determine dimensions of the Menu and a mPopupMsg to specify placement of a popup Menu.

/* 10 */

resource'MENU' (kMDEF, "1st Floating Tearoff Menu",
 purgeable)
{
kMDEF,
// By my convention, MDEF ID = Menu ID:
kMDEF,
0x7FFFFFFF,
enabled,
"Tear off this hummer !!!",
{
/* Item(s) drawn “on-the-fly” by
** DrawMenu as discussed below.  */
}
};

#define mMovie   20

resource 'MBAR' (MBARapp, "MBAR", purgeable)
{
{/* array MenuArray: 5 elements */
 /* [1] */
 mApple,
 /* [2] */
 mFile,
 /* [3] */
 mEdit,
 /* [4] */
 mMovie,
 /* [5] */
 kTearMenu
}
};

void  CMovieApp::SetUpMenus (void)
{
 CTearMenuDir  *cryBaby   = nil;

 /* Superclass takes care of 
 ** adding menus specified in
 ** a MBAR id = 1 resource:   */
 inherited::SetUpMenus();

 /* Director for a tear-off Menu:
 ** ( I’ll explain later on. )*/
 cryBaby = new (CTearMenuDir);
 // Supervisor = your app:
 cryBaby->ITearMenuDir(this);
 itsTearMenu = cryBaby;

}/* SetUpMenus */

Remember that your CMovieApp::SetUpMenus calls inherited::SetUpMenus so that your 'MBAR' resource gets loaded into memory to create the main Menubar, including your Tear-Off Menu. Internal to this loading process, _GetMenu is called and thus the menuDefProc field of the tear-off 'MENU' resource gets filled in with a Handle to my 'MDEF'. _GetMenu is able to accomplish this because the 'MENU' resource contains the ID of the 'MDEF' that should be used. I will explain later my initialization routine = ITearMenuDir. In the meantime, however, the latter eventually calls ITearOffMenu to create your floating window as well as IMenuDefProc to fill the defProc field of your 'MDEF' stub with the effective address of TCL’s GenericMDEF. It looks like we’re almost in business. Before I blow town, i.e., exit my ITearMenuDir, I move the blasted window off-screen so it’s not seen. In short, I keep it handy for later when I tear-off the Menu.

/* 11 */

void  CMenuDefProc::IMenuDefProc (short MDEFid)
{
 GenericMDEFHand theMDEF;

 theMDEF = (GenericMDEFHand) GetResource('MDEF', MDEFid);
 FailNILRes(theMDEF);
 (**theMDEF).defProc = (VoidFunc) GenericMDEF;
 // last 4 bytes of stub:
 (**theMDEF).itsMenuDefProc = this;
 FlushCache();
}

IMenuDefProc also fills in the last four bytes of your 'MDEF' resource stub with the object that was sent the message to begin with and that object is a descendant of CMenuDefProc. I’ll talk about which descendant later but in the meantime, recall when I stated above that thanks to _GetMenu and IMenuDefProc the Menu Manager will jump to the address of TCL’s GenericMDEF. The TCL depicts the latter as:

/* 12 */

pascal void GenericMDEF (short theMessage, register 
 MenuHandle macMenu, Rect *menuRect, Point hitPt,
 short *whichItem)
{
 GenericMDEFHand theMDEF;
 CMenuDefProc  *theMenuDefProc;

 theMDEF = (GenericMDEFHand) (**macMenu).menuProc;
 /* itsMenuDefProc = “this”
 ** in IMenuDefProc: */
 theMenuDefProc = (**theMDEF).itsMenuDefProc;

 switch (theMessage)
 {
 case mDrawMsg:
 theMenuDefProc-> DrawMenu(macMenu, menuRect);
 break;

 // etc.
 }
}

Remember that the object stored in the itsMenuDefProc field of your 'MDEF' stub is the object that was sent the message = IMenuDefProc and said object is our mystical descendant of CMenuDefProc. So in short, for example, when _MenuSelect sends a mDrawMsg to our 'MDEF', we end up calling CMenuDefProc::DrawMenu(...), or really the DrawMenu method of its descendant since the latter must override the parent’s DrawMenu because the parent’s DrawMenu is empty. “Simple, ain’t it ?!*!?”

/* 13 */

class CMenuDefProc : public CObject
{
public:

void  IMenuDefProc(short MDEFid);

virtual voidDrawMenu(MenuHandle macMenu, Rect *menuRect);
virtual voidChooseItem(MenuHandle macMenu, Rect *menuRect, Point hitPt, 
short *whichItem);
virtual voidSizeMenu(MenuHandle macMenu);
virtual voidPlacePopup(MenuHandle macMenu, Rect *menuRect, Point hitPt, 
short *whichItem);
};

and in similiar fashion for the other messages.

Let’s review the bidding

Okay, now I think it’s time to reveal what ITearMenuDir looks like:

/* 14 */

void  CTearMenuDir::ITearMenuDir (CApplication *aSupervisor)
{
 CCustomSelector *myMenu = NULL;
 CSelectorMDEF   *myMDEF = NULL;
 BooleansavedAlloc;
 PicHandlemyPic;
 Rect   pictRect;

First, call ITearOffMenu to create a floating window with ID = kTearMenu and set itsWindow from CTearOffMenu's superclass = CDirector. CMovieApp::SetUpMenus passed this as the Tear-Off Menu's Supervisor. this is referenced within a CMovieApp method, so this must be my application. Therefore, my app supervises my Tear-Off Menu.

ITearOffMenu, in the process of creating our floating window, passes this as the window’s supervisor . This this is the object that was sent our message = ITearOffMenu, which I called cryBaby within my SetUpMenus method (go back a couple of pages to confirm this). So, the this passed as the floating window’s supervisor is our Tear-Off Menu object = CTearMenuDir. As a direct result, our app supervises our Tear-Off Menu which, in turn, supervises our floating window.

“A director is a bureaucrat that supervises a window.” The above is consistent with this because CTearMenuDir descends from CTearOffMenu which descends from CDirector. Down a little bit we will make the supervisor of the CGridSelector (is a CSelector is a CPanorama is a CPane is a sub-view of our floating window) our application. Normally, the supervisor of a CPane is a document.

I mentioned way, way back within this article’s introduction that a CGridSelector is functionally a palette or array of grid elements wherein each Menu item of our Tear-Off Menu is a distinct pane or grid element of this CGridSelector. The fact that I have only one grid element or pane in my very simple array becomes relevant only to the discussion of Command Numbers which I’m intentionally postponing until further on.

/* 15 */

inherited::ITearOffMenu(aSupervisor, kTearMenu);

// Get size of grid element:
savedAlloc = SetAllocation(kAllocCanFail);
myPic = GetPicture(kMAC);
SetAllocation(savedAlloc);
FailNILRes(myPic);
pictRect = (**myPic).picFrame;
// Zero origin:
OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
// Do NOT need after getting frame:
ReleaseResource(myPic);

IGridSelector calls ISelector which calls IPanorama which calls IPane to do all the requisite initialization of instance variables, including those of CGridSelector. For example:

• how many rows and columns are there in my grid array? (since I have only one item, my values are 1, 1)

• the width and height of each grid element (yes I’m implying that all grid elements have the identical size)

These next two instance variables are inherited from CSelector:

• when I pull down the Tear-Off Menu what item is initially highlighted? (the first item has a number = 1)

• the Command Base for my grid array of Menu items (I elected this to be equal to the ID of my TOM)

/* 16 */
myMenu = new (CCustomSelector);
myMenu->IGridSelector
 (
 itsWindow, /* From superclass of CTearOffMenu */
 aSupervisor,  /* My application */
 0, 0,
 sizELASTIC, sizELASTIC,
 0,/* Initial item to select = none in
 ** this case since items are numbered
 ** beginning at 1 */
 kTearMenu, /* Command Base */
 1, 1,  /* # of rows & columns */
 pictRect.right + 2, /* box width */
 pictRect.bottom + 2 /* & height */
 );

aSupervisor is successively passed up the inheritance chain to IBureaucrat and stored in CBureaucrat::itsSupervisor to handle the Commands that our CGridSelector (= = CView = CBureaucrat) cannot handle. I will discuss this key point in detail shortly.

IGridSelector sets CGridSelector::gridOn = true. Since I have only 1 element in my simple example, I don’t need a grid of orthogonal lines whose primary purpose in life is to visually differentiate adjacent multiple grid elements:

/* 17 */

myMenu->SetGridOn(false);
myMenu->FitToEnclosure(true, true);
myMenu->Activate();

itsPane = CTearOffMenu::itsPane = a CPane. My CCustomSelector = a CGridSelector = a CSelector = a CPanorama = a CPane. Therefore, both are CPanes and can be equated. More on this later:

/* 18 */

itsPane = myMenu;

Reset the minimum & maximum sizes of a window. TCL has these preset = 100 & GrayRgn's rgnBBox, respectively:

/* 19 */

SetRect(&itsWindow->sizeRect,
 pictRect.left  - 1,
 pictRect.top   - 1,
 pictRect.right   + 3,
 pictRect.bottom + 3);

Change the size of all the window's sub-view(s), the latter being now just my CGridSelector = myMenu in my simplistic example. Leave a blank 1 pixel border around the picture so it does NOT touch the window frame:

/* 20 */

itsWindow->ChangeSize(pictRect.right + 2, 
 pictRect.bottom + 2);

Leave same blank space in setting margins. This margin ALSO includes the regular window frame. So we have a 1 pixel blank space, a 1 pixel frame AND a 10 pixel drag bar on top:

/* 21 */

SetRect(&margins, 2, 12, 2, 2);

Now a real toughie

Go back to the segment of my introduction wherein I talked about ITearOffMenu, IGridSelector and ISelectorMDEF. The bottom line there was that CTearOffMenu::itsPane = CPaneMDEF::itsPane = my new CGridSelector. The first and third pieces are equated above (itsPane = myMenu). When we pass my new CGridSelector to ISelectorMDEF below, the same CGridSelector is passed to IPaneMDEF which then equates the second and third pieces.

/* 22 */

myMDEF = new (CSelectorMDEF);
myMDEF->ISelectorMDEF(kTearMenu, myMenu, this);

What I deliberately postponed telling you ’til now is that also passed to ISelectorMDEF is this which is the object that was sent the original message = ITearMenuDir which is my cryBaby addressed in my CMovieApp::SetUpMenus. cryBaby is a CTearMenuDir is a CTearOffMenu is a CDirector. ISelectorMDEF not only passes on my CGridSelector object ( = myMenu) to IPaneMDEF for stuffing into CPaneMDEF::itsPane, but it also passes on cryBaby. IPaneMDEF then stuffs cryBaby into CPaneMDEF::itsTearOffMenu. This last stuffing is used by the TCL when I discuss later on tearing off your Menu so hold this thought as well.

AHHHHH-HAH!!!

Remember back a few pages when I said that a descendant of CMenuDefProc gets sent a DrawMenu message when _MenuSelect sends a mDrawMsg to TCL’s GenericMDEF. Well the descendant is CSelectorMDEF and it’s this descendant object that IMenuDefProc, called by my ITearMenuDir within CMovieApp::SetUpMenus, stuffs into the itsMenuDefProc field of my 'MDEF' resource stub.

Dig into the TCL source code and observe that CSelectorMDEF does not have a DrawMenu method; however, its superclass = CPaneMDEF does. So when TCL’s GenericMDEF calls DrawMenu, CPaneMDEF::DrawMenu gets called. Ditto for SizeMenu. If responding to a mChooseMsg CSelectorMDEF::ChooseItem gets called; in short, CSelectorMDEF does not have to travel up to its superclass to find a ChooseItem method. Finally, if responding to a mPopupMsg, we need to travel all the way up to CMenuDefProc to access CMenuDefProc::PlacePopup since none of the sub-classes of CMenuDefProc have a PlacePopup method.

The DrawMenu routine of CPaneMDEF calls itsPane->Draw where itsPane is an instance variable of CPaneMDEF. Note from previous discussions that IPaneMDEF stuffs my CGridSelector object {which is a CSelector is a CPanorama which descends from CPane} into the itsPane instance variable belonging to CPaneMDEF.

So, when CPaneMDEF::DrawMenu is eventually called by TCL’s GenericMDEF, CPaneMDEF::itsPane->Draw gets called. Since itsPane is a CGridSelector object, take a gander at CGridSelector::Draw. The latter sweeps through all the rows and columns of your CGridSelector matrix of elements, or really array of Menu items, and calls CGridSelector::DrawItem for each element or Menu item.

Let’s blow town:

/* 23 */

 // Keep handy, but out of the way:
 itsWindow->MoveOffScreen();
 itsWindow->Select();
}/* ITearMenuDir */

Here’s what my own DrawItem method looks like:

/* 24 */

void  CCustomSelector::DrawItem (short theItem, Rect *theBox)
{
/* Passed area rect is in QuickDraw coordinates */

 #define  kMAC   3000

 BooleansavedAlloc;
 PicHandlemyPic;
 Rect   pictRect;
 
 switch (theItem){
 
 case 1:
 savedAlloc = SetAllocation(kAllocCanFail);
 myPic = GetPicture(kMAC);
 SetAllocation(savedAlloc);
 FailNILRes(myPic);

 pictRect = (**myPic).picFrame;
 CenterRects(&pictRect, theBox);
 DrawPicture(myPic, &pictRect);

 /* Do NOT need after drawing: */
 ReleaseResource(myPic);
 break;
 
 default:
 // Empty for now:
 inherited::DrawItem(theItem, theBox); 
 break; 
 } /* only 1 item */
}/* DrawItem */

Once again, notice that I only have one pane or grid element or Menu item. Given a more complex grid of Menu items, take a gander at Figure 37-1 in Symantec’s “Object Oriented Programming Manual” for the numbering scheme associated with multiple grids.

Tear Off this hummer

Let’s talk a little bit more about CTearOffMenu:

/* 25 */

class CTearOffMenu : public CDirector
{
public:
 CPane  *itsPane;
 Point  corner;
 Rect   margins;

 void   ITearOffMenu (CApplication *aSupervisor,
 short WINDid);

 virtual void  Suspend (void);
 virtual void  Resume (void);
 virtual void  CloseWind (CWindow *theWindow);
 
 virtual void  TornOff (Point aCorner);
 virtual void  MoveToCorner (void);
 virtual WindowPtr  GetMacWindow (void);
 virtual void  SetMargins (Rect *aMargins);
 virtual void  GetMargins (Rect *theMargins);
};

I’ve already presented a flood of words about ITearOffMenu. The Suspend and Resume methods call CWindow::HideSuspend and CWindow::ShowResume to make the Tear-Off Menu disappear and re-appear, respectively, per the specifications of Apple’s Human Interface Guidelines. I’ll postpone addressing CloseWind until later (trust me!!!).

CSelectorMDEF::ChooseItem method detects a Tear-Off event by following your dragging motion. If you’ve dragged beyond the confines of the pulled-down Menu and not stayed within them as you would for a normal choose, then CPaneMDEF::TearOffMenu is called. After some moderate housekeeping, CPaneMDEF::itsTearOffMenu->TornOff is eventually called. Remember when I said a zillion words ago that IPaneMDEF stuffed my CTearOffMenu object = cryBaby into CPaneMDEF::itsTearOffMenu? Well “there she blows!”.

With the calling of TornOff, a new CTearChore is created, initialized and subsequently added to CApplication::itsUrgentChores via:

/* 26 */

gApplication-> AssignUrgentChore(newTearChore);

When ITearChore is called by AssignUrgentChore, this is passed as a parameter where this = the object that was sent the original message. The original message = TornOff, so this this = CPaneMDEF::itsTearOffMenu. ITearChore places the passed this into the instance variable = CTearChore::itsTearOffMenu.

AssignUrgentChore calls:

/* 27 */

 newTearChore->Perform();

which then calls:

/* 28 */

 newTearChore::itsTearOffMenu-> MoveToCorner();

CTearOffMenu::MoveToCorner eventually calls _MoveWindow, passing TRUE as the update parameter. An update Event occurs and guess what !!! Remember, thanks to CMovieApp::SetUpMenus, my window has been hiding in the weeds, i.e., off-screen. The “corner” the window is moved to is CTearOffMenu::corner, which is initialized to {0, 0} by ITearOffMenu. Given a tear-off as detected by ChooseItem (described above), CTearOffMenu::TornOff is called. Passed to TornOff is a single parameter = the mouse location in local Menu pane coordinates. The TCL has already setup the GrafPort so that its origin is the topLeft of the Menu. This is why when there is no tear off and the corner instance variable remains at its initialized value = {0, 0}, the Menu simply “plops down”. When there is a tear-off and TornOff is called, the passed corner changes with the mouse movement and is stored in CTearOffMenu::corner. When _MoveWindow is subsequently called, it’s passed the instance variable. As a direct result, the Tear-Off Menu follows your mouse as you drag.

Let’s start to pick up some loose pieces that we’ve only touched on so far.

The two remaining methods of your CApplication that you should override are DoCommand and DoKeyDown.

command numbers

I still need to talk about how tear-off Menus assign Command Numbers, but here is a kernel for this method so we can subsequently discuss Command Numbers in a logical manner:

/* 29 */

void  CMovieApp::DoCommand (long theCommand)
{
 GrafPtrsavePort;
 Str255 theDAName;

 if (theCommand < 0)
 {
 if (HiShort(-theCommand) == MENUapple)
 {
 /* BIG-time TCL boo-boo for not 
 ** saving & restoring Port:   */
 GetPort(&savePort);
 GetItem(GetMHandle(MENUapple), LoShort(-theCommand),
 theDAName);
 OpenDeskAcc(theDAName);
 SetPort(savePort);
 }
 else if (HiShort(-theCommand) == kTearMenu)
 {
 enum {
 OFF,
 ONApple = MENUapple
 };
 HiliteMenu(ONApple);
 DoCommand(cmdAbout);
 HiliteMenu(OFF);
 } 
 else
 inherited::DoCommand(theCommand);
 
 } /* end: theCommand < 0 */
 else /* theCommand > 0 */
 {
 switch (theCommand)
 {
 case cmdAbout:
 TRY
 {
 }
 CATCH
 {
 }
 ENDTRY;
 break; /* cmdAbout */
 
 // etc.

 default:
 
 inherited::DoCommand(theCommand); 
 } /* end: switch */
 } /* end: theCommand > 0 */
}/* DoCommand */

First, note that I have placed the test for a TOM Command Number in my application’s DoCommand method. Go back a page or so and review the fact that the supervisor of a TOM is your app (I pass this to ITearMenuDir within the CMovieApp’s SetUpMenus). Also recall that the superisor of my TOM’s main pane, my CGridSelector, is also my app. Notice that this Command Number is negative which unambiguously implies that it’s created “on-the-fly”. These are key points, so keep them safe.

Additionally see that within my app’s version of DoCommand, I only test for the high word of the Command Number, that is, the Menu ID. I am not interested in the low word = the Menu item because my CGridSelector has only one pane. If I had a Tear-Off Menu akin to MacPaint’s Pattern Menu I would have multiple grid elements whose Command Numbers were separated by one. As a direct result, I would then be concerned with the low word.

Two zillion words ago I stated that my CMovieApp::SetUpMenus called my ITearMenuDir method and that the latter called IGridSelector. Go back and review that my CGridSelector serves as my Tear-Off Menu’s main CPane when I call:

/* 30 */

 itsPane = myMenu;

IGridSelector, in turn, calls ISelector to place the passed Command Number base integer into CSelector::commandBase. For my simplistic example wherein my Tear-Off Menu has only one pane or grid element or Menu item, I simply pass the ID of my TOM.

Tear-Off the Menu ...

Assuming you tear-off the Menu then, as I’ve previously explained, CPaneMDEF’s TearOffMenu is dutifully called the latter eventually calls CTearOffMenu’s TornOff method to create a new urgent CTearChore and assign said CTearChore to gApplication by calling CApplication::AssignUrgentChore the latter calls CTearChore::Perform which, in turn, calls CTearOffMenu’s MoveToCorner the latter finally calls _MoveWindow to allow the Torn-Off Menu to follow your dragging motion.

Okay, I’m off

Given a tear-off, then we access our pane(s) or Menu item(s) by clicking on them just as if we were clicking on a pane of an ordinary, oh-hum window. CSwitchboard’s DoMouseDown effects the necessary processing by calling gDesktop->DispatchClick (remember, our gDesktop is really a CFWDesktop object). DispatchClick calls _FindWindow to determine where we clicked. Naturally, the returned partCode = inContent in which case CWindow::DispatchClick is called. The latter calls CView::DispatchClick to find out which sub-View has been hit via a call to CView::FindSubView. Given success, CView::DispatchClick calls the pertinent sub-View’s DoClick method. The pertinent sub-View is a CGridSelector object which inherits DoClick from its superclass = CSelector. The pertinent sub-View is my CGridSelector because within my ITearMenuDir I call:

/* 31 */

 myMenu->IGridSelector(...);

Because a CGridSelector (= myMenu) is a CPane, after several jumps up the inheritance chain, eventually IGridSelector calls IPaneX which calls:

/* 32 */

 itsEnclosure->AddSubView(this);

where the pane’s enclosure = our floating window and this = my CGridSelector. Eventually, the TCL calls CView::AddSubView which does exactly that add the sub-View to the CWindow’s CList instance variable = CView::itsSubViews.

I have chosen to “roll my own” DoClick method as follows:

/* 33 */

void  CCustomSelector::DoClick (Point hitPt,
 short modifierKeys, long when)
{
 short  itemHit, count;
 long   finalTicks;
 extern short  gClicks;
 
 itemHit = FindItem(hitPt);

 // Ignore all clicks beyond 2:
 if ( (itemHit != selection) &&
   (gClicks == 2) )
 {
 for (count = 2; count > 0; count--)
 {
 HiliteItem(itemHit, hiliteON);
 Delay(20, &finalTicks);
 HiliteItem(itemHit, hiliteOFF);
 Delay(20, &finalTicks);
 }
 itsSupervisor->DoCommand(-(((long)commandBase << 16 ) + 
 itemHit));
 }
}/* DoClick */

Notice that when we call IGridSelector from within ITearMenuDir, the CMovieApp is passed as the supervisor to handle the Commands that our CGridSelector ( = = CBureaucrat) cannot handle. So when DoClick calls:

/* 34 */

 itsSupervisor->DoCommand(...);

CMovieApp::DoCommand is really being called, another reason for testing for a Tear Menu Command Number within your CApplication’s DoCommand. Also, note that we negate the Command Number when we call DoCommand, thus creating the Command Number “on the fly”.

No tear-off

What about pulling down the Menu, but not tearing it off? CSelectorMDEF::ChooseItem calls CSelector’s special HiliteItem method and then stuffs the selected item number into the *whichItem passed by reference to ChooseItem by the Menu Manager just like it’s normally done. ChooseItem fills in the low memory long word global = MenuDisable and exits.

In this scenario, i.e., no tear-off, ChooseItem was originally called by _MenuSelect which returns a long word with the Menu ID in the High word and the Menu item in the low word. _MenuSelect is called from within CDesktop::DispatchClick. The latter continues by calling CBartender’s FindCmdNumber and passing the result to:

/* 35*/

 gGopher->DoCommand(cmdNbr);

FindCmdNumber, quite naturally, finds our Tear-Off Menu because we placed its ID in our 'MBAR' resource. However, since we did not place any Command Numbers in our Tear-Off 'MENU' resource, FindCmdNumber returns the negative of the Tear-Off Menu ID in the High word and the negative of the selected Menu item in the low word of the composite long word result. Just like a 'FONT' Menu or the Apple Menu, eh? So, once again, we have a negative Command Number just as we did when we executed CSelector’s DoClick method.

Whew I thought I was in trouble for a second

What’s the gGopher here?

Maybe you have just activated a oh-hum window supervised by a particular CDocument in which case the gGopher becomes that document (see my August, 1992 article). The TCL goes to yourDoc->DoCommand. If the TCL fails to find the appropriate Command Number there, the TCL calls:

/* 36 */

 inherited::DoCommand( );

Since a CDocument is a CDirector is a CDirectorOwner is a CBureaucrat, we wind our way up to CBureaucrat::DoCommand which then calls:

/* 37 */

 itsSupervisor->DoCommand( );

We are now looking at the supervisor of the CDocument and that is our app.

Okay that’s one down.

Maybe we have just torn off our Menu, so CTearOffMenu::MoveToCorner is eventually called as previously described. CWindow::Select is called after the window is moved to follow your mouse. When CWindow::Activate is subsequently called, CDirector::Activate ends up being called. The latter detects that we have a floating window, so CBureaucrat::BecomeGopher is not called. As a direct result, the gGopher stays put, remaining whatever it was as a result of our non-floating windows. So we end up going to CMovieApp::DoCommand just as we did before we tore-off our Menu.

HyperCard™ anyone

In order to fill in the details of showing/hiding my floating window via pressing <CMD-Tab>, let me present my app’s DoKeyDown method, explaining as I go:

/* 38 */

void  CMovieApp::DoKeyDown (char theChar, Byte keyCode, EventRecord *macEvent)
{
 enum {
 OFF,
 ONApple = MENUapple
 };
 long   finalTicks;
 WindowPeek tearPeek;
 Point  tlWind,
 defaultPt = {100, 100};
 Rect   desk;
 CWindow*theWindow;

 if (macEvent->modifiers & cmdKey)
 {
 if (theChar == '/')
 {
 HiliteMenu(ONApple);
 DoCommand(cmdAbout);
 HiliteMenu(OFF);
 } /* CMD-? */ 
 else if (keyCode == 0x0D)
 { /* = 'w', regardless
 ** of modifier key*/
 if (macEvent->modifiers & optionKey)
 { // = <CMD-Option> w
 theWindow = gDesktop-> GetTopWindow();
 while (theWindow != nil)
 {
 theWindow->Close();
 theWindow = gDesktop-> GetTopWindow();
 }
 }
 }

 // okay, now we get to my <CMD-Tab> stuff:
 else if (keyCode == 0x30 ||
 keyCode == 0x48)  // <Tab>
 {
 if (itsTearMenu->corner.h == 0 && 
  itsTearMenu->corner.v == 0)

Never torn-off before. The reason is that when ITearOffMenu is called by my ITearMenuDir, CTearOffMenu::corner is initialized to {0, 0} and does not change until we tear-off the Menu. Only then does CTearOffMenu::TornOff get called to create a new CTearChore. Subsequently, CTearOffMenu::MoveToCorner is called to alter the instance variable = corner. As a direct result, we must call the TornOff method directly to execute a tear-off:

/* 39 */
          
 itsTearMenu-> TornOff(defaultPt);
 
 else
 {
 // Toggle between show & hide:
 tearPeek = (WindowPeek) itsTearMenu->GetMacWindow();
 tlWind = topLeft( (**(tearPeek ->contRgn)).rgnBBox );
 ((CFWDesktop*)gDesktop)-> GetBounds(&desk);
 
 if (tlWind.v > desk.bottom && 
  tlWind.h > desk.right)

Torn-off before, BUT subsequently closed because CTearOffMenu::CloseWind calls CWindow::MoveOffScreen. Put the window back where it was BEFORE you closed it:

/* 40 */

 itsTearMenu-> TornOff(itsTearMenu->corner);
 else
 itsTearMenu-> CloseWind(itsTearMenu->itsWindow);
 }
 
 } /* CMD-Tab */
 } /* CMD-key pressed */
 else if (keyCode == KeyHelp)
 {
 HiliteMenu(ONApple);
 DoCommand(cmdAbout);
 HiliteMenu(OFF);
 } /* Help Key */
 else inherited::DoKeyDown(theChar, keyCode, macEvent);
}/* DoKeyDown */

Overidding CloseWind, inherited from CTearOffMenu’s superclass = CDirector, completes the discussion:

/* 41 */

void  CTearMenuDir::CloseWind (CWindow *theWindow)
{
 WindowPeek tearPeek;
 Point  tlWind;

If we insist on toggling the showing/hiding of the torn-off Menu via a keystroke, we canNOT save the current position of the associated window JUST in our DoKeyDown(...) method. For example, what if we move our window, close it by clicking in the goAway box and then hit <CMD-Tab> to re-show it. The window will be shown in its position prior to our move. We could do our saving within our application's Idle() method, but that consumes unnecessary time.

/* 42 */

 tearPeek = (WindowPeek) GetMacWindow();
 // corner in GLOBAL coordinates:
 tlWind = topLeft( (**(tearPeek-> contRgn)).rgnBBox );

 SetPt(&corner, tlWind.h, tlWind.v);

 inherited::CloseWind(theWindow);
}/* CloseWind */

 
AAPL
$97.19
Apple Inc.
+2.47
MSFT
$44.87
Microsoft Corpora
+0.04
GOOG
$595.98
Google Inc.
+1.24

MacTech Search:
Community Search:

Software Updates via MacUpdate

Firefox 31.0 - Fast, safe Web browser. (...
Firefox for Mac offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals... Read more
Little Snitch 3.3.3 - Alerts you to outg...
Little Snitch gives you control over your private outgoing data. Track background activityAs soon as your computer connects to the Internet, applications often have permission to send any... Read more
Thunderbird 31.0 - Email client from Moz...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
Together 3.2 - Store and organize all of...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Smart storage. With simple drag-and-drop functionality,... Read more
Cyberduck 4.5 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
iExplorer 3.4 - View and transfer all th...
iExplorer is an iPhone browser for Mac lets you view the files on your iOS device. By using a drag and drop interface, you can quickly copy files and folders between your Mac and your iPhone or... Read more
Airmail 1.4 - Powerful, minimal email cl...
Airmail is a powerful, minimal mail client.It was designed to retain the same experience with a single or multiple accounts and provide a quick, modern and easy-to-use user experience. Airmail... Read more
Macs Fan Control 1.1.12 - Monitor and co...
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
A Better Finder Rename 9.37 - File, phot...
A Better Finder Rename is the most complete renaming solution available on the market today. That's why, since 1996, tens of thousands of hobbyists, professionals and businesses depend on A Better... Read more
MacBook Air EFI Firmware Update 2.9 - Fo...
MacBook Air EFI Firmware Update is recommended for MacBook Air (Mid 2011) models. This update addresses an issue where systems may take longer to wake from sleep than expected and fixes a rare issue... Read more

Latest Forum Discussions

See All

Ex-Angry Birds Developers Release Monsu...
Ex-Angry Birds Developers Release Monsu Teaser Trailer Posted by Jennifer Allen on July 23rd, 2014 [ permalink ] Finnish developer Boomlagoon has released a teaser trailer of their forthcoming side-scrolling action platformer, | Read more »
Lots of New Modes Have Been Added to Can...
Lots of New Modes Have Been Added to Canabalt Posted by Jennifer Allen on July 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Stronghold 3: The Campaigns Review
Stronghold 3: The Campaigns Review By Jennifer Allen on July 23rd, 2014 Our Rating: :: DULL STRATEGIZINGiPad Only App - Designed for the iPad A cumbersome strategy game, Stronghold 3: The Campaigns has a few too many issues to... | Read more »
Table Tennis Touch on Sale for a Limited...
Table Tennis Touch on Sale for a Limited Time Posted by Jessica Fisher on July 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Secret Files Tunguska Review
Secret Files Tunguska Review By Jennifer Allen on July 23rd, 2014 Our Rating: :: CONSPIRACY-LITTERED ADVENTURINGUniversal App - Designed for iPhone and iPad Offering traditional adventuring with no fear of in-app purchases, Secret... | Read more »
Celebrate Summer With a Cat in the Hat L...
Celebrate Summer With a Cat in the Hat Learning Library Sale Posted by Ellis Spice on July 22nd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Dragon Raiders Review
Dragon Raiders Review By Nadia Oxford on July 22nd, 2014 Our Rating: :: RUN, DRAGON, RUNUniversal App - Designed for iPhone and iPad Dragon Raiders is rough and scaly in some parts, but overall it’s an enjoyable level-based running... | Read more »
MyTaskList Review
MyTaskList Review By Jennifer Allen on July 22nd, 2014 Our Rating: :: EFFECTIVE IF PLAINUniversal App - Designed for iPhone and iPad It’s not the most stylish of task management apps, but MyTaskList has all the features you could... | Read more »
FlyCraft Herbie: Crazy Machines Review
FlyCraft Herbie: Crazy Machines Review By Jennifer Allen on July 22nd, 2014 Our Rating: :: TRICKY FLYINGUniversal App - Designed for iPhone and iPad A tough game of careful thrusting and navigation, FlyCraft Herbie: Crazy Machines... | Read more »
MTN Review
MTN Review By Jessica Fisher on July 22nd, 2014 Our Rating: :: ADORABLE, SERENE, AND AMUSINGUniversal App - Designed for iPhone and iPad MTN is an adorable, talking pet mountain that is less game and more zen garden.   | Read more »

Price Scanner via MacPrices.net

With The Apple/IBM Alliance, Is The iPad Now...
Almost since the iPad was rolled out in 2010, and especially after Apple made a 128 GB storage configuration available in 2012, there’s been debate over whether the iPad is a serious tool for... Read more
MacBook Airs on sale starting at $799, free s...
B&H Photo has the new 2014 MacBook Airs on sale for up to $100 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels... Read more
Apple 27″ Thunderbolt Display (refurbished) a...
The Apple Store has Apple Certified Refurbished 27″ Thunderbolt Displays available for $799 including free shipping. That’s $200 off the cost of new models. Read more
WaterField Designs Unveils Cycling Ride Pouch...
High end computer case and bag maker WaterField Designs of San Francisco now enters the cycling market with the introduction of the Cycling Ride Pouch – an upscale toolkit with a scratch-free iPhone... Read more
Kingston Digital Ships Large Capacity Near 1T...
Kingston Digital, Inc., the Flash memory affiliate of Kingston Technology Company, Inc.,has announced its latest addition to the SSDNow V300 series, the V310. The Kingston SSDNow V310 solid-state... Read more
Apple’s Fiscal Third Quarter Results; Record...
Apple has announced financial results for its fiscal 2014 third quarter ended June 28, 2014, racking up quarterly revenue of $37.4 billion and quarterly net profit of $7.7 billion, or $1.28 per... Read more
15-inch 2.0GHz MacBook Pro Retina on sale for...
B&H Photo has the 15″ 2.0GHz Retina MacBook Pro on sale for $1829 including free shipping plus NY sales tax only. Their price is $170 off MSRP. B&H will also include free copies of Parallels... Read more
Apple restocks refurbished Mac minis for up t...
The Apple Store has restocked Apple Certified Refurbished Mac minis for up to $150 off the cost of new models. Apple’s one-year warranty is included with each mini, and shipping is free: - 2.5GHz Mac... Read more
Twelve South HiRise For MacBook – Height-Adju...
If you use your MacBook as a workhorse desktop substitute, as many of us do, a laptop stand combined with an external keyboard and pointing device are pretty much obligatory if you want to avoid... Read more
Why The Mac Was Not Included In The Apple/IBM...
TUAW’s Yoni Heisler cites Fredrick Paul of Network World whoi blogged last week that the Mac’s conspicuous absence from Apple and IBM’s landmark partnership agreement represents a huge squandered... Read more

Jobs Board

Sr Software Lead Engineer, *Apple* Online S...
**Job Summary** The Apple Online Store is looking for a highly motivated, entrepreneurial senior software engineer to join the Apple Online Store Publishing Systems 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
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* 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.