TweetFollow Us on Twitter

Shapes in Quickdraw
Volume Number:2
Issue Number:12
Column Tag:ABC's of C

Drawing Shapes with Quickdraw

By Bob Gordon , Contributing Editor

One problem with writing software is that friends often want to know what it does. With most of these columns, frankly, there has not been much to show. This time, though, you can use the mouse to draw some simple shapes on the screen. Of course your friends will point out that MacDraw does everything we're going to do, and much better, too. But this one, we did ourselves, and that makes all the difference!

QuickDraw Shapes and Operations

QuickDraw can draw a number of shapes. This month we are going to cover only the simple shapes. (I define simple shapes as those that can be drawn directly without first defining what the shape is.) The simple shapes are:

Rectangles

Ovals (ellipses and circles)

Round-cornered rectangles

Arcs and wedges

To this list we could also add lines. The functions to draw these shapes are built into the Mac's ROM.

In drawing the shape, QuickDraw can do a number of different operations:

Frame draws a hollow outline

Paint fills the shape with the current grafPort's pen pattern and mode.

Erase fills the shape with the background pattern

Invert inverts all pixels within the shape: black becomes white and white becomes black

Fill fills the shapes with a specified pattern.

In general, these operations work identically for all the shapes. The shape is drawn, and the pen's location is not changed. Except for Fill, the operations require only the information needed to define the shape. Fill also needs to know the pattern to use. Since we have no easy way to select a pattern (we haven't done custom menus yet, so we haven't made a pattern selection menu), this operation will not be used.

The Toolbox supplies a separate function for each shape and operation. There are, for example, five functions to draw rectangles:FrameRect(), PaintRect(), EraseRect(), InvertRect(), and FillRect(). I wanted to select the shape and operation from menus and then draw with the mouse as with MacDraw.

Fig. 1 Our Drawing Program

Alternative Designs

One way to do this (assuming we had the menus built) would be to use a switch (case) statement based on the shape and operation:

switch (shape)
 case rect:
 switch (operation)
  case Frame:
  case Paint:
  case Erase:
  case Invert:
  case Fill:
  case oval:
 switch (operation)
 
 et cetera 

This is a sort of brute force method. It would work, but it involves several pages of code to make a couple of simple selections.

Another approach is to take advantage of C's ability to pass and use pointers to functions. To do this we obtain the addresses of the functions and arrange them in a double subscripted array. The problem of selection reduces to a problem of indexing into the array.

Pointers to Functions

Just as we can get the address of a variable and then assign a pointer to it, we can get the address of a function, assign a pointer to it and use the pointer to access the function. Kernighan and Ritchie discuss this on page 114.

There are several step in using a pointer to a function. First, to get the address of a function, just use the name of the function without the parentheses. If fr_rect() is a function, fr_rect will be the address of the of the function. To use a function in this manner we must create a variable that is a pointer to a function. The following line does this:

 short  (*drfunc)();

This rather strange looking line declares drfunc to be a pointer to a function that returns a short. Note that the parentheses around *afunc are required. Without them we would have:

 short  *drfunc();

a function that returns a pointer to a short. I could not use this declaration directly in the program but had to use a typedef:

 typedef short (*drfunc)();

Once this type is established, we can define some variables. In the program there is a variable, draw.

 drfunc draw;

For the moment assume that draw points to a function (it has been assigned a value). To use draw we do the following:

 (*draw)(par1,par2);

Again, the parentheses are needed to indicate that draw is a pointer to a function and we want to execute the function it points to. (Without the parentheses draw would be a function that returns a pointer). It is important to pass the proper number of variables. Since the call to the function is made through a pointer, compilers can do very little checking.

The Drawing Functions

I had originally hoped to avoid writing a bunch of drawing functions, but this plan changed. First, Lightspeed C does not allow us to take the address of Toolbox functions. They even have a special error message. This probably has to do with how they access the Toolbox and make the translation from C to Pascal calling conventions. This meant I would need at least a surround function for each Toolbox routine I wished to use.

Secondly, I wanted to draw lines in the same way as the other shapes. Since the Toolbox does not handle lines as shapes, I would have to do it myself. This was complicated by the fact that the initial versions of these functions expected to receive rectangles. Rectangles are used to define all the shapes. With lines, though, it meant taking apart the rectangle, figuring out which corner was the beginning, and keeping track of it. Needless to say, the line functions got very strange looking. To simplify the line functions, all the functions now receive two points. This had the side benefit of simplifying the oval functions, but it required that the surround routines create a rectangle before calling the Toolbox function.

The other requirement for accessing the function via a pointer is that all the functions must receive the same number of parameters. In addition to a rectangle, the round rectangle functions get two parameters describing the oval width and height used in drawing the rounded corner. These are fixed at 20. (Do try varying these. I was able to make some very ugly rounded rectangles). The arcs receive a start angle and the number of degress of angle to move (arcAngle in Toolbox terms). I fixed the arc angle at 90°. The start angle and the sign of the arc angle are adjusted as necessary to make the arc move correctly. These arcs were modeled after the ones in MacDraw.

The result of all this is a single function, drdraw(), that draws all the simple shapes under mouse control!

Speaking of the Mouse

Another addition to the program this month is the code that changes the cursor. While it is not yet complete (it doesn't know about the window borders where the controls would go), it does change the cursor as the mouse moves around. AdjustCursor() receives a pointer to a window record as a parameter and sets the cursor to the crosshairs (cursor number two) if the mouse is in the window and to the arrow if the mouse is not. The arrow cursor itself is not one of the four standard cursors but is defined in Quickdraw.h. AdjustCursor() is called once each time through the event loop.

There are two other points that deserve some mention. One is that several sets of coordinates can be active at once. GetMouse(), for example, returns the mouse's position relative to the current or active window. The window's boundaries, however, are defined in terms of the screen or global coordinates. The functions LocalToGlobal() and GlobalToLocal() will switch a point's coordinate system. Without the switch, the cursor changes magically out in the middle of the screen.

Next Time

We only did the simple shapes this time. I decided to wait on the others pending a discussion of the memory manager. Many of the functions we have used so far make use of the memory manager, and to do some things, we must be able to grab bits of memory. After that (I expect the program to be very brief - just long enough to demonstrate the operation) we'll return to Quickdraw and draw some more shapes.

The Program

/* abc.h 
 *
 * Local definitions to improve readability
 *
 */*
 
#defineTrue 1
#define False    0
#define Nil 0
#define and &&
#define or||
#define not !
#define equals   ==
#define notequal !=

/* unsigned char,longs, shorts
 * (unsigned longs may not be 
 *  available with all compilers
 */
#define uchar    unsigned char
#define ushort   unsigned short
#define ulong    unsigned long

/* General purpose external routines */

extern  char*CtoPstr(); /* String conversion routines */
extern  char*PtoCstr(); /* return a pointer to a char */


/*  Quickdraw Drawing Program
 *    Shows off basic quickdraw shapes
 * and operations.
 * By Bob Gordon for MacTutor.
 * Compiled with LightspeedC
 *
 * Important note for Mac C users:
 * Every place you see event->where,
 * replace it with &event->where
 */
 #include "abc.h"
 #include "Quickdraw.h"
 #include "EventMgr.h"  /* Events.h */
 #include "WindowMgr.h" /* Window.h */
 #include "MenuMgr.h"/* Menu.h */
 /* defines for menu ID's */
 #defineMdesk    100
 #defineMfile    101
 #defineMedit    102
 #defineMshape 103
 #defineMop 104
 /* File */
 #defineiNew1
 #defineiClose 2
 #defineiQuit    3
 /* Edit */
 #defineiUndo    1
 #defineiCut3
 #defineiCopy    4
 #defineiPaste 5
 
 /* Global variables */
 
 MenuHandle menuDesk;/* menu handles */
 MenuHandle menuFile;
 MenuHandle menuEdit;
 MenuHandle menuShape;
 MenuHandle menuOp;
 WindowPtrtheWindow;
 WindowRecord  windowRec;
 Rect   dragbound;
 Rect   limitRect;
 
main()
{
 initsys(); /* system initialization */
 initapp(); /* application initialization */
 eventloop();
}

/* system initialization */
initsys() 
{
 InitGraf(&thePort); /* these two lines done */
 InitFonts();    /* automatically by Mac C */
 InitWindows();
 InitCursor();
 InitMenus();
 theWindow = Nil;/*indicates no window */
 SetRect(&dragbound,0,0,512,250);
 SetRect(&limitRect,60,40,508,244);
}

/* application initialization  */
initapp()
{
 setupmenu();
 drinit();
}

setupmenu()
{
 menuDesk = NewMenu(Mdesk,CtoPstr("\24"));
 AddResMenu (menuDesk, 'DRVR');
 InsertMenu (menuDesk, 0);
 
 menuFile = NewMenu(Mfile, CtoPstr("File"));
 AppendMenu (menuFile,CtoPstr("New/N;Close;Quit/Q"));
 InsertMenu (menuFile, 0);
 
 menuEdit = NewMenu(Medit, CtoPstr("Edit"));
 AppendMenu (menuEdit,CtoPstr("(Undo/Z;(-;(Cut/X;( Copy/C;( Paste/V;(Clear"));
 InsertMenu (menuEdit, 0);
 
 menuShape = NewMenu(Mshape, CtoPstr("Shape"));
 AppendMenu (menuShape,CtoPstr("Line;Rectangle; Oval;Round Rectangle;Arc"));
 InsertMenu (menuShape, 0);
 
 menuOp = NewMenu(Mop, CtoPstr("Operation"));
 AppendMenu (menuOp,CtoPstr("Frame;Paint; Erase;Invert;"));
 InsertMenu (menuOp, 0);
 DrawMenuBar();
}
 
/* Event Loop */
eventloop()
{
 EventRecordtheEvent;
 char   c;
 short  windowcode;
 WindowPtrww;

 while(True)
 {
 if (theWindow)      
 { 
 EnableItem(menuFile,2);  
 DisableItem(menuFile,1);
 AdjustCursor(theWindow);
 }
 else   
 { 
 EnableItem(menuFile,1);
 DisableItem(menuFile,2);
 }
 if (GetNextEvent(everyEvent,&theEvent))
 switch(theEvent.what)  
 { 
 case keyDown:   
 c = theEvent.message & charCodeMask;
 if (theEvent.modifiers & cmdKey)
 domenu(MenuKey(c));
 else if (theWindow)
 break;
 case mouseDown:
 domousedown(&theEvent);
 break;
 default:
 break;
 } 
 }
}

/* Arrow or Plus Cursor shape */
AdjustCursor(w)
 WindowRecord  *w;
{
 Point  pt;
 CursHandle curs;
 
 GetMouse(&pt);
 LocalToGlobal(&pt);
 if (PtInRgn(pt,w->contRgn))
 {
 curs = (Cursor **)GetCursor(2); 
 SetCursor(*curs); 
 }
 else
 {
 SetCursor(&arrow);
 }
}

/* domousedown
 * handle mouse down events
 */
domousedown(er)
 EventRecord*er;
{
 short  windowcode;
 WindowPtrwhichWindow;
 short  ingo;
 long   size;
 long   newsize;
 RgnPtr rp;
 Rect   box;
 Rect   *boxp;
 
 windowcode = FindWindow(er->where, 
 &whichWindow);
 switch (windowcode)
 {
 case inDesk:
 if (theWindow notequal 0)
 {
 HiliteWindow(theWindow, False);
 DrawGrowIcon(theWindow);
 }
 break;
 case inMenuBar:
 domenu(MenuSelect(er->where));
 break;
 case inSysWindow:
 SysBeep(1);
 break;
 case inContent:
 if (whichWindow equals theWindow)
 {
 HiliteWindow(whichWindow,True);
 DrawGrowIcon(whichWindow);
 drdraw(whichWindow);
 }
 break;
 case inDrag:
 DragWindow(whichWindow, 
   er->where, &dragbound);
 DrawGrowIcon(whichWindow);
 break;
 case inGrow:
 break;
 case inGoAway:
 ingo = TrackGoAway(whichWindow,er->where);
 if (ingo)
 {
 CloseWindow(whichWindow);
 theWindow = Nil;
 }
 break;
 }
}

/* domenu
 * handles menu activity
 * simply a dispatcher for each
 * menu.
 */
domenu(mc)
 long   mc; /* menu result */
{
 short  menuId;
 short  menuitem;

 menuId = HiWord(mc);
 menuitem = LoWord(mc);
 switch (menuId)
 {
 case Mdesk : break;
 /* not handling DA's */
 case Mfile : dofile(menuitem);
  break;
 case Medit : /* all disabled */
  break;
 case Mshape: doshape(menuitem);
  break;
 case Mop   : dooper(menuitem);
  break;
 }
 HiliteMenu(0);
}

doshape(item)
 short  item;
{
 static short  lastitem;
 
 CheckItem (menuShape,lastitem,False);
 CheckItem (menuShape,item,True);
 lastitem = item;
 drshape(item);
}

dooper(item)
 short  item;
{
 static short  lastitem;
 
 CheckItem (menuOp, lastitem,False);
 CheckItem (menuOp, item, True);
 if (item == 5)
 {
   item = 0;
   SysBeep(1);
   }
 droper(lastitem = item);
}

dofile(item)
 short  item;
{
 char   *title1; /*title for window */
 Rect   boundsRect;
 
 switch (item)
 {
 case iNew :/* open the window */
 title1 = "ABC Window";
 SetRect(&boundsRect,50,50,400,200);
 theWindow = NewWindow(&windowRec, &boundsRect,CtoPstr(title1), True, 
documentProc,
(WindowPtr) -1, True, 0);
 DrawGrowIcon(theWindow);
 PtoCstr(title1);
 DisableItem(menuFile,1);
 EnableItem(menuFile,2);
 break;
 case iClose :   /* close the window */
 CloseWindow(theWindow);
 theWindow = Nil;
 DisableItem(menuFile,2);
 EnableItem(menuFile,1);
 break;
 case iQuit :    /* Quit */
 ExitToShell();
 break; 
 }
}



/* 
 * dr.c
 * drawing routines
 */
 #include "abc.h"
 #include "quickdraw.h"
 #include "windowMgr.h"
 
struct shapes
 {
 short  kind;
 Rect size;
 short  oper;
 };
 
struct shapes    shapa[20];
short   shapdx;

fr_line(startpt,endpt)
 Point  startpt,endpt;
{
 MoveTo(startpt.h,startpt.v);
 LineTo(endpt.h,endpt.v);
}

fr_rect(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Pt2Rect(startpt,endpt,&rt);
 FrameRect(&rt);
}

fr_oval(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Pt2Rect(startpt,endpt,&rt);
 FrameOval(&rt);
}

fr_rort(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Pt2Rect(startpt,endpt,&rt);
 FrameRoundRect(&rt,20,20);
}


fr_arc(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Rect trt;
 short  sa;
 short  aa;
 Pt2Rect(startpt,endpt,&rt);
 cp_arc(&rt,&trt,&sa,&aa);
 FrameArc (&trt,sa,aa);
}

cp_arc(irt,ort,startangle,arcangle)
 Rect *irt;
 Rect *ort;
 short  *startangle;
 short  *arcangle;
{
 short  dh;
 short  dv;
 static Point  anchor;
 dh = irt->right - irt->left;
 dv = irt->bottom - irt->top;
 if (not (dh | dv))
 {
 anchor.v = irt->top;
 anchor.h = irt->left;
 }
 *ort = *irt;
 if (irt->left equals anchor.h)
 if (irt->top < anchor.v)
 {
 ort->left -= dh;
 ort->top -= dv;
 *startangle = 180;
 *arcangle = -90;
 }
 else
 {
 ort->left -= dh;
 ort->bottom += dv;
 *startangle = 0;
 *arcangle = 90;
 }
 else
 if (irt->top < anchor.v)
 {
 ort->top -= dv;
 ort->right += dh;
 *startangle = 180;
 *arcangle = 90;
 }
 else
 {
 ort->right += dh;
 ort->bottom += dv;
 *startangle = 0;
 *arcangle = - 90;
 }
}

er_line(startpt,endpt)
 Point  startpt,endpt;
{
 GrafPtrgp;
 Patterntpat;
 GetPort(&gp);
 BlockMove(gp->pnPat,&tpat,8);
 PenPat(gp->bkPat);
 MoveTo(startpt.h,startpt.v);
 LineTo(endpt.h,endpt.v);
 PenPat(&tpat);
}

er_rect(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Pt2Rect(startpt,endpt,&rt);
 EraseRect(&rt);
}

er_oval(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Pt2Rect(startpt,endpt,&rt);
 EraseOval(&rt);
}

er_rort(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Pt2Rect(startpt,endpt,&rt);
 EraseRoundRect(&rt,20,20);
}

er_arc(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Rect trt;
 short  sa;
 short  aa;
 
 Pt2Rect(startpt,endpt,&rt);
 cp_arc(&rt,&trt,&sa,&aa);
 EraseArc (&trt,sa,aa);
}

pt_line(startpt,endpt)
 Point  startpt,endpt;
{
 GrafPtrgp;
 Patterntpat;
 
 MoveTo(startpt.h,startpt.v);
 LineTo(endpt.h,endpt.v);
}

pt_rect(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 
 Pt2Rect(startpt,endpt,&rt);
 PaintRect(&rt);
}

pt_oval(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 
 Pt2Rect(startpt,endpt,&rt);
 PaintOval(&rt);
}

pt_rort(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 
 Pt2Rect(startpt,endpt,&rt);
 PaintRoundRect(&rt,20,20);
}

pt_arc(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Rect trt;
 short  sa;
 short  aa;
 
 Pt2Rect(startpt,endpt,&rt);
 cp_arc(&rt,&trt,&sa,&aa);
 PaintArc (&trt,sa,aa);
}

in_line(startpt,endpt)
 Point  startpt,endpt;
{
 GrafPtrgp;
 short  tpnMode;
 
 GetPort(&gp);
 tpnMode = gp->pnMode;
 PenMode(patXor);
 MoveTo(startpt.h,startpt.v);
 LineTo(endpt.h,endpt.v);
 PenMode(tpnMode);
}

in_rect(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 
 Pt2Rect(startpt,endpt,&rt);
 InvertRect(&rt);
}

in_oval(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 
 Pt2Rect(startpt,endpt,&rt);
 InvertOval(&rt);
}

in_rort(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 
 Pt2Rect(startpt,endpt,&rt);
 InvertRoundRect(&rt,20,20);
}

in_arc(startpt,endpt)
 Point  startpt,endpt;
{
 Rect rt;
 Rect trt;
 short  sa;
 short  aa;
 
 Pt2Rect(startpt,endpt,&rt);
 cp_arc(&rt,&trt,&sa,&aa);
 InvertArc (&trt,sa,aa);
}
 
typedef short  (*drfunc)();
drfunc  a[][5] = {fr_line,fr_rect,fr_oval,fr_rort,fr_arc,
 pt_line,pt_rect,pt_oval,pt_rort,pt_arc,
 er_line, er_rect,er_oval, er_rort,er_arc,
  in_line,in_rect,in_oval, in_rort,in_arc};
drinit()
{
 short  i;
 for (i = 0; i < 20; shapa[i++].kind = 0)
 ;
 shapdx = 0;
}
drshape(code)
 short  code;
{
 shapa[shapdx].kind = code;
}
droper(code)
 short  code;
{
 shapa[shapdx].oper = code;
}
drsize(r)
 Rect *r;
{
 shapa[shapdx].size = *r;
}
drdraw(w)
 WindowRecord  *w;
{
 Point  startpt;
 Point  thispt;
 Point  endpt;
 Point  lastpt;
 Rect   thisrt;
 Rect   lastrt;
 GrafPtrport;
 drfunc frame;
 drfunc draw;
 short  angle;
 short  dv,dh;
 Point  sp;
 Point  tp;
 Point  lp;
 short  shapx;
 short  operx;
 
 SetPort((GrafPtr)w);
 GetMouse(&startpt);
 lastpt = startpt;
 PenMode(patXor);
 PenPat(gray);
 shapx = shapa[shapdx].kind - 1;
 operx = shapa[shapdx].oper - 1;
 if ((shapx < 0) or (operx < 0))   /* to prevent trying */
 return;/* to use unselected items */
 frame = a[0][shapx];/* get address of frame func */
 draw  = a[operx][shapx]; /* get addr of shape/oper func */
 do{
 GetMouse(&endpt);
 thispt = endpt;
 LocalToGlobal(&endpt);
 if (PtInRgn(endpt,w->contRgn) and 
 not EqualPt(thispt,lastpt))
 {
 (*frame)(startpt,lastpt);
 (*frame)(startpt,thispt);
 lastpt = thispt;
 }
 }
 while (StillDown());
 (*frame)(startpt,thispt);
 PenMode(patCopy);
 PenPat(black);
 (*draw)(startpt,thispt); 
}

abs(num)
 short  num;
{
 if (num < 0 )
 return -num;
 return num;
/* num < 0 ? return -num : return num ;*/
}   
 
AAPL
$467.36
Apple Inc.
+0.00
MSFT
$32.87
Microsoft Corpora
+0.00
GOOG
$885.51
Google Inc.
+0.00

MacTech Search:
Community Search:

Software Updates via MacUpdate

Acorn 4.1 - 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
Mellel 3.2.3 - Powerful word processor w...
Mellel is the leading word processor for OS X, and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
Iridient Developer 2.2 - Powerful image...
Iridient Developer (was RAW Developer) is a powerful image conversion application designed specifically for OS X. Iridient Developer gives advanced photographers total control over every aspect of... Read more
Delicious Library 3.1.2 - Import, browse...
Delicious Library allows you to import, browse, and share all your books, movies, music, and video games with Delicious Library. Run your very own library from your home or office using our... Read more
Epson Printer Drivers for OS X 2.15 - Fo...
Epson Printer Drivers includes the latest printing and scanning software for OS X 10.6, 10.7, and 10.8. Click here for a list of supported Epson printers and scanners.OS X 10.6 or laterDownload Now Read more
Freeway Pro 6.1.0 - Drag-and-drop Web de...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With it's user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Transmission 2.82 - Popular BitTorrent c...
Transmission is a fast, easy and free multi-platform BitTorrent client. Transmission sets initial preferences so things "Just Work", while advanced features like watch directories, bad peer blocking... Read more
Google Earth Web Plug-in 7.1.1.1888 - Em...
Google Earth Plug-in and its JavaScript API let you embed Google Earth, a true 3D digital globe, into your Web pages. Using the API you can draw markers and lines, drape images over the terrain, add... Read more
Google Earth 7.1.1.1888 - View and contr...
Google Earth gives you a wealth of imagery and geographic information. Explore destinations like Maui and Paris, or browse content from Wikipedia, National Geographic, and more. Google Earth... Read more
SMARTReporter 3.1.1 - Hard drive pre-fai...
SMARTReporter is an application that can warn you of some hard disk drive failures before they actually happen! It does so by periodically polling the S.M.A.R.T. status of your hard disk drive. S.M.... Read more

Strategy & Tactics: World War II Upd...
Strategy & Tactics: World War II Update Adds Two New Scenarios Posted by Andrew Stevens on August 12th, 2013 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Expenses Planner Review
Expenses Planner Review By Angela LaFollette on August 12th, 2013 Our Rating: :: PLAIN AND SIMPLEUniversal App - Designed for iPhone and iPad Expenses Planner keeps track of future bills through due date reminders, and it also... | Read more »
Kinesis: Strategy in Motion Brings An Ad...
Kinesis: Strategy in Motion Brings An Adaptation Of The Classic Strategic Board Game To iOS Posted by Andrew Stevens on August 12th, 2013 [ | Read more »
Z-Man Games Creates New Studio, Will Bri...
Z-Man Games Creates New Studio, Will Bring A Digital Version of Pandemic! | Read more »
Minutely Review
Minutely Review By Jennifer Allen on August 12th, 2013 Our Rating: :: CROWDSOURCING WEATHERiPhone App - Designed for the iPhone, compatible with the iPad Work together to track proper weather conditions no matter what area of the... | Read more »
10tons Discuss Publishing Fantasy Hack n...
Recently announced, Trouserheart looks like quite the quirky, DeathSpank-style fantasy action game. Notably, it’s a game that is being published by established Finnish games studio, 10tons and developed by similarly established and Finnish firm,... | Read more »
Boat Watch Lets You Track Ships From Por...
Boat Watch Lets You Track Ships From Port To Port Posted by Andrew Stevens on August 12th, 2013 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Expenses Review
Expenses Review By Ruairi O'Gallchoir on August 12th, 2013 Our Rating: :: STUNNINGiPhone App - Designed for the iPhone, compatible with the iPad Although focussing primarily on expenses, Expenses still manages to make tracking... | Read more »
teggle is Gameplay Made Simple, has Play...
teggle is Gameplay Made Simple, has Players Swiping for High Scores Posted by Andrew Stevens on August 12th, 2013 [ permalink ] | Read more »
How To: Manage iCloud Settings
iCloud, much like life, is a scary and often unknowable thing that doesn’t always work the way it should. But much like life, if you know the little things and tweaks, you can make it work much better for you. I think that’s how life works, anyway.... | Read more »

Price Scanner via MacPrices.net

13″ 2.5GHz MacBook Pro on sale for $150 off M...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $1049.95 including free shipping. Their price is $150 off MSRP plus NY sales tax only. B&H will include free copies of Parallels Desktop... Read more
iPod touch (refurbished) available for up to...
The Apple Store is now offering a full line of Apple Certified Refurbished 2012 iPod touches for up to $70 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free: -... Read more
27″ Apple Display (refurbished) available for...
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
Apple TV (refurbished) now available for only...
The Apple Store has Apple Certified Refurbished 2012 Apple TVs now available for $75 including free shipping. That’s $24 off the cost of new models. Apple’s one-year warranty is standard. Read more
AnandTech Reviews 2013 MacBook Air (11-inch)...
AnandTech is never the first out with Apple new product reviews, but I’m always interested in reading their detailed, in-depth analyses of Macs and iDevices. AnandTech’s Vivek Gowri bought and tried... Read more
iPad, Tab, Nexus, Surface, And Kindle Fire: W...
VentureBeat’s John Koetsier says: The iPad may have lost the tablet wars to an army of Android tabs, but its still first in peoples hearts. Second place, however, belongs to a somewhat unlikely... Read more
Should You Buy An iPad mini Or An iPad 4?
Macworld UK’s David Price addresses the conundrum of which iPAd to buy? Apple iPad 4, iPad 2, iPad mini? Or hold out for the iPad mini 2 or the iPad 5? Price notes that potential Apple iPad... Read more
iDraw 2.3 A More Economical Alternative To Ad...
If you’re a working graphics pro, you can probably justify paying the stiff monthly rental fee to use Adobe’s Creative Cloud, including the paradigm-setting vector drawing app. Adobe Illustrator. If... Read more
New Documentary By Director Werner Herzog Sho...
Injuring or even killing someone because you were texting while driving is a life-changing experience. There are countless stories of people who took their eyes off the road for a second and ended up... Read more
AppleCare Protection Plans on sale for up to...
B&H Photo has 3-Year AppleCare Warranties on sale for up to $105 off MSRP including free shipping plus NY sales tax only: - Mac Laptops 15″ and Above: $244 $105 off MSRP - Mac Laptops 13″ and... Read more

Jobs Board

Sales Representative - *Apple* Honda - Appl...
APPLE HONDA AUTOMOTIVE CAREER FAIR! NOW HIRING AUTO SALES REPS, AUTO SERVICE BDC REPS & AUTOMOTIVE BILLER! NO EXPERIENCE NEEDED! Apple Honda is offering YOU a Read more
*Apple* Developer Support Advisor - Portugue...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more than Read more
RBB - *Apple* OS X Platform Engineer - Barc...
RBB - Apple OS X Platform Engineer Ref 63198 Country USA…protected by law. Main Function | The engineering of Apple OS X based solutions, in line with customer and Read more
RBB - Core Software Engineer - Mac Platform (...
RBB - Core Software Engineer - Mac Platform ( Apple OS X) Ref 63199 Country USA City Dallas Business Area Global Technology Contract Type Permanent Estimated publish end Read more
*Apple* Desktop Analyst - Infinity Consultin...
Job Title: Apple Desktop Analyst Location: Yonkers, NY Job Type: Contract to hire Ref No: 13-02843 Date: 2013-07-30 Find other jobs in Yonkers Desktop Analyst The Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.