TweetFollow Us on Twitter

PictButton
Volume Number:9
Issue Number:1
Column Tag:Visual Programming

Related Info: Color QuickDraw Picture Utilities Quickdraw Control Manager

A Pictorial Button Class in Prograph

A dynamic and fluid development environment

By Terry Kilshaw, Kelowna, British Columbia

In an article in the now justly famous Smalltalk edition of Byte Magazine for August 1981, Larry Tessler refers to the notion of an Integrated Environment, a concept he ascribes to Alan Kay. He says “In an Integrated Environment, a person can interweave activities without losing accumulated information and without giving up capabilities”. Smalltalk led the way into forms of programming which dissolved the barriers between process and product. HyperCard, with its powerful emphasis on the direct manipulation of visual elements, introduced a new sort of programming which could not have existed but for the Xerox work. Apple built on that work, and Bill Atkinson's special talents and vision took the “oriented” out of “object-oriented” and let users get their hands on their programs for the first time.

The Prograph programming environment presents another approach to the goal of an Integrated Environment. In this article I will attempt, through the somewhat static and linear medium of print with illustrations, to convey some aspects of this dynamic and fluid development environment.

About Prograph

Prograph is certainly worthy of note for a number of reasons: as a clean implementation of a single inheritance object-oriented language, because textual code with all of its syntactic problems is eliminated in favour of the use of data-flow diagrams, because its list processing capabilities give it much of the power of Lisp and Prolog, because its System Classes and their associated editors provide the sort of ease of interface construction that HyperCard and SuperCard users have come to expect, and for almost complete access to the Mac Toolbox. But what is really significant about this development environment is the synergy between these elements and the dissolution of the usual boundary between “editing mode” and “execution mode” normally found in most other programming environments. It is the main goal of this article to try to convey a little of what it is like to program in Prograph.

The Prograph System Classes

The Prograph programming environment provides a set of System Classes which define the most commonly used elements of the Macintosh User Interface. Here are the System Classes as they appear in Prograph. The lines which connect the class icons show inheritance.

We will make a simple button class which acts just like a normal Macintosh button but which displays a Macintosh Picture. A Picture is a Macintosh data type which is simple to make. Whenever you cut or copy part of an image in a paint program it goes into the Macintosh clipboard as a PICT resource. Inits such as Capture also allow you to copy any area of the screen directly into the clipboard as a PICT. From the clipboard you can paste a PICT into the Scrapbook for safekeeping, or paste it directly into a Prograph Pict item in the Prograph Window Editor. A PICT can be of any size and, if you have color capability, your Pictures can also be in color.

To help readers who don't have Prograph to get a feel for this sort of programming I'll explain some of the actual process, what is clicked, where clicks occur, and so on. But for the sake of brevity some of the steps will be just briefly described.

We start by loading the System Classes file and saving it under the name PButton Class.pgs. The .pgs suffix is for later use by the Prograph compiler. It stands for Prograph Source File. Of course you don't need to start from the System Classes if you want to create a new class, but we will be inheriting behavior from a System Class and will be using the Application, Window and Menu classes in the development process.

Creating a Class

Classes are defined and manipulated in the Classes window. We create our new class as a sub-class of Pict (see above). To make it easier to follow, all of the classes which are not direct predecessors of the new class can be hidden. With the icon of class Pict selected, hold down the option key and click in space. A new class icon appears with an inheritance arc connecting it to the icon of class Pict and you can type in its name, PButton.

Inherited Attributes

The new PButton class inherits both the data structures (or attributes), and the behaviors (or methods) of its ancestor classes. What inheritance really means is that a PButton is a sort of Pict which is a sort of Graphic, which is a sort of Window Item.

Double clicking on the left side of a class icon opens a window onto its attributes. If you do this for the new PButton you will see some small triangular icons, in a single column, which look like this.

This attribute icon has a downward pointing arrow in it to show that it has been inherited, from class Pict above, and it has an extra outline around it, which means that it is a system attribute. Prograph uses many subtle visual indicators like this.

A system attribute is one that can't be deleted and whose value, when set, can create certain side-effects. For example, location is a point that determines the top-left corner position of the PButton within its window. When your program is running, changing this value will cause the PButton to change position within its window.

Although there are various intrinsic behaviors associated with System Classes, you will not find any method icons in the Methods window of this class or in any of its ancestors. All of the System Class behaviors are accomplished behind the scenes and are made available to the programmer by the act of getting and setting the value of a System Class attribute. This is similar to the way properties work in HyperCard.

Scroll the attributes window until the attribute called click method is in view and then double click on it. A window will open to allow you to change the attribute's value. Type in “PButton/mouseDown” and press the return key.

What we have just done is to set the default value of the attribute click method for every instance which will be produced. When the mouse is clicked in a PButton, Prograph will call the method whose name is found in the click method attribute, that is, method mouseDown of class PButton. Later we will create this method.

Creating a new Attribute

Scroll the attributes window to the bottom and click in space beneath the last attribute. A plain triangular attribute icon will appear. Visually this indicates an attribute that is neither inherited nor a system attribute. Name it mouseUp method. Double click on this attribute and give it the default value of the empty string.

When we create a new PButton we will set the value of its mouseUp method attribute to the name of the method to be called whenever the mouse is released over the PButton. This will be probably be different for every PButton.

Making a Method

Double clicking on the right side of a class icon opens a window onto its methods. The PButton class has no methods, so we will create one which will be used later as the method called when the mouse is released over our PButton.

Clicking once in space creates a method icon which we will call do PB1. Later we will name the PButton that we create PB1. There is no programmatic reason for this name, only mnemonic value. You may have a dozen PButtons and keeping straight which one does what can be a problem.

Double clicking on the method's icon opens a window showing the first case of the method do PB1. A Prograph Method consists of one or more cases. Each case appears in its own window and is its own self-contained data-flow diagram. Case 1 looks like this.

The long thin rectangle near the top of the window is the input bar operation. The long thin rectangle at the bottom of the window is the output bar operation. Every case has an input bar and an output bar. Nothing need be attached to either of them if the method has no inputs or outputs, as is true in this case.

Creating a Method

Clicking once in space in the case window will create a rectangular simple operation icon with an active text editor on it. Typing in SysBeep and pressing the return key will cause the name SysBeep to be looked up in the internal list of Prograph primitive names and the list of Macintosh method names. Prograph provides more than 180 primitives which deal with such things as list and string manipulation, file access, comparison and so on. More than 1000 Macintosh toolbox routines are available as Mac Methods. SysBeep is the name of a toolbox routine familiar to most Mac programmers. When Prograph finds the SysBeep reference it knows to annotate the operation to look like a Mac method call. This is indicated by the extra lines along the top and bottom of the operation. At the same time the required number of inputs and outputs are added to the operation. It needs one input. Double clicking on the input terminal automatically creates a constant operation with the default value of NULL. Type in the value 1. SysBeep requires an input value which specifies the duration of the beep. This value has been ignored by SysBeep since System 6.0 appeared, for reasons known only to Apple, but a valid integer argument is still needed for Prograph to make the call. After tidying up the window a little our first method looks like this.

The window title indicates that this is a method in class PButton named do PB1 and that this is case 1 from a total of 1 cases. When executed it will cause your Macintosh to beep, squawk, screech or whatever you have set on the control panel as your alert sound. Test it if you like by choosing the Execute Method item from the Execution menu. Just make sure that the case window is the current front window or that the PButton Methods window is at the front and the method do PB1 is selected.

Creating a Test-Bed

We could go on writing the rest of the code in the normal abstract way. Instead, we will first create an actual window and a PButton using Prograph's interactive WYSIWYG editors. We will paste a PICT from the Scrapbook into the PButton item, exit the editors, and then start to execute the program using the window and PButton item we have created as a test-bed for further development. Because of space restrictions I'll just outline very briefly the steps to take.

Go into the Application Editor, create a new Window instance, add it to the Active List and invoke the Window Editor on it. Create a Window Item and change it to a PButton item. Give it the name PB1 and the ID # 1. Copy your desired PICT from the Scrapbook and paste it into the PButton. Command-option-click on the PButton item to open the Value window on its instance and set the value of attribute mouseUp method to “//do PB1”. Exit the Window and Application Editors.

Review

So far we have created the PButton class and set the value of its click method attribute to “PButton/mouseDown” - the name of the method which should be called whenever a click occurs on that button. We have added a new attribute to the class called mouseUp method, whose default value is the empty string. Then, for our development test-bed, we created a Window instance using the Application Editor, interactively created a PButton instance in the Window Editor, pasted our chosen PICT into it and set the name of the method which should be called whenever the mouse is released within the PButton to “//do PB1”.

Now we are ready to start writing the “code”. First we must define how a PButton should behave. As long as the mouse is down, within the rectangular bounds of the button, it should be hilited. If the cursor strays outside the bounds, the button should un-hilite. If the mouse is released outside of the button, nothing should happen. If it is released inside the button, the method whose name is found in the attribute mouseUp Method should be called.

Execution and Run-Time Method Creation

Choose the Run initial item from the Execution menu and the menu bar will change to show a File menu with the single item Quit in it. This menu and the quit method, found in the Menu class, are provided in the System Classes. The window which we made earlier will appear with its PButton. Mine looks like this.

The double stave was captured from the screen of a music notation program and the vertical “bar-lines” were added in a paint program before being pasted into my Scrapbook.

Clicking on the PButton item produces a dialog which says “Prograph is attempting to dispatch an event to a method called 'mouseDown' in class 'PButton'. That method does not exist. Do you want to create it?” Pressing the OK button produces this window.

This is the execution window for case 1 of the method mouseDown in class PButton. The dotted background shows that this is code which is currently executing. Because Prograph uses data-flow diagrams to describe code (rather than control flow diagrams, as VIP does, for example), execution always begins with the first case of a method and, if necessary, is directed to the next case using control mechanisms to be described later in this article.

The input bar is shown selected. It will be the next operation to be executed in the case. The three gray blobs attached to it are input roots. After this operation has been executed, the input roots will be un-grayed and will hold the data values input to the method. You can execute the operation by pressing the return key, and can then examine the input values by double clicking on each root in turn. From the left, their values are: the instance of the window which owns the PButton, the instance of the PButton itself, and the Macintosh EventRecord for the click event.

Editing a Method

Double clicking anywhere on the dotted background of the window opens an editing window in which we can start writing our code. Remember that the program is still running. We are in the middle of an execution but it is OK to edit the code.

Actual details of how to create Prograph operations, how to annotate them to specify different functionality, control flow and so on, I'll leave to the user and to the comprehensive tutorial and reference manuals provided with Prograph. For the sake of space I'll have to use the Julia Childs approach at this point and start showing you the finished methods, with just a little of the editing process where the techniques are unusual or significant.

The mouseDown Method

Here is the completed case, showing the top level of the method:

There are various types of operation to be seen here.

Syntax of Early and Late Binding

get-bounds and invert-button are both calls to user defined methods which have not yet been created. The // prefix in these method calls specifies that the search for the method to execute should begin in the class of the method in which the call appears, in this case class PButton. Prograph is an object-oriented language, part of which implies that the resolution of which method to call can be deferred until runtime. In this case we know precisely where to find our methods. All of them are in the class PButton, so runtime dispatching is not necessary. The notation //method is shorthand for class/method when you are editing code in the target class. The other possibility is /method which means that the method should be looked for at runtime. Methods of the same name may exist in various different classes and the one which will be called will depend on the type of the instance fed to the left-most input of the calling operation. In compiled code it is more expensive to call methods whose class must be resolved at runtime.

The operation “while mouseDown” is a local method - indicated by the white bands at either end. “while mouseDown” is not really the name of the method, but just a sort of comment. That's why its name is not shown in boldface. This method is local only to this case. It is the graphical equivalent of a nesting construct like Begin...End in Pascal. Local methods help to reduce visual complexity and are used for looping and selection of alternative execution paths. Local methods can be nested within each other as deeply as required. This operation has its left-most terminal and root annotated together as a loop. Whatever is output to the root on the bottom of the operation will be fed back in as the input to the terminal on the top for the next iteration of the loop. This also means that the operation will be called repeatedly until some control within it tells it to stop.

The first operation with TRUE in it is a constant. Its value is the Boolean TRUE, which is fed into the local operation for the first iteration of the loop.

The other operation which displays TRUE is a match. The round cornered square on the right end of the match operation, with an X in the middle and a little black line across the top, is a control. All control flow decisions in Prograph are determined by control annotations on operations such as these. This control can be read as ”if the input value is not TRUE, terminate this method without executing any other operation“. That will be the condition if the mouse is released outside of the PButton. Otherwise execution of the case proceeds as normal to the next operation.

The mouseUp method operation is annotated as a get attribute (indicated by the > shaped indent on its left end). You may recall that mouseUp method is the name of the attribute that we added to the PButton class. When this operation is called, with a PButton instance as input, it will output the value of attribute mouseUp method on its right root and will pass the PButton instance on on its left root.

The unnamed operation with the terminal sticking into it is an ordinary call to a method. It has no name because the name of the method to be called will be “injected” into it at runtime through the “inject terminal” that you can see. In our example the injected name will be “//do PB1”. Remember that the value of the mouseUp Method attribute can be different for every PButton. Using an inject here allows us to write generic code which will work for all PButtons.

Creating Methods on the Fly

When you double click on the left end of the get-bounds operation the Prograph Editor searches for a method called get-bounds in class PButton. If it is found, an editing window will be opened onto the first case of that method. If it is not found, then the method is first created before its first case is opened. This is a short cut for the method creation process we used when making do PB1.

Here is the code for get-bounds.

Comments on Comments

“<<Window Item>>” and “item bounds rect” are both comments. Comments have no logical significance in Prograph. Every class, method, attribute, persistent, operation, root and terminal in a Prograph program can have its own comment, and each comment can be up to 32K long. I am a minimal commenter and usually restrict myself to one comment for each input and output in a case. The double pointed brackets which surround the words Window Item are a Prograph convention which means “an instance of the indicated class or a subclass thereof”. The get-bounds method could actually be used to get the bounding rectangle of any type of Window Item. To use it for that purpose it needs to be in class Window Item to make it visible to all subclasses of Window Item.

The location and size of the window item are accessed from the input instance using the two get operations. The AddPt operation is a Macintosh method call. It expects two points as inputs, adds the two X coordinates and the two Y coordinates of each point and produces the bottom-right corner of the the item's bounds as output.

The points-to-rect operation is a Prograph primitive. This is visually distinguished by the extra line across the bottom of its icon. It takes the top-left corner point and the bottom-right corner point and creates the bounds rectangle which is then sent to the output bar and is returned as the result of the method.

Continuing Execution and Roll-Back

You can bring the dotted background execution window back to the front now, and, by holding down the shift key while pressing the return key, you can continue execution, stepping into the code of get-bounds. After each operation has been executed you can double click on its roots to examine its output values. You can roll execution back to any operation in a case by holding the command key down and clicking on the operation you want to roll back to.

Roll-back is an essential part of Prograph programming. An extremely tight loop can exist between editing and executing code. If you make changes to a case which is currently being executed, roll-back will be done for you automatically. In this way it is rarely necessary, after editing, to begin executing your program right from the start. Prograph also makes it possible to roll back on the case and method level and you can even roll forwards within a case, within certain limitations.

The invert button Method

The method invert-button can be created in the same way as get-bounds, by double clicking on the left side of its operation.

The Macintosh WindowRecord pointer is extracted from the Window instance and fed to the Mac method SetPort. This makes the PButton's window the active GrafPort and means that any drawing or coordinate measuring Mac methods will operate with the correct context. The Mac method InvertRect hilites the PButton. The row of semi-circles pointing from SetPort to InvertRect form what is called a Synchro. Data-flow within this case does not constrain the order of execution, but we need to ensure that the port is set before the rectangle is inverted. The Synchro enforces this priority.

Creating a Local Method

A double click on the local method “while mouseDown” opens a window onto its first case. As can be seen from the window’s title bar, we are looking at case 1 of a 3 case method. Of course if you are creating this, the method will start with only one case.

There are no data dependencies between the two operations on the right and the group on the left; however, because a control is attached to the match whose input comes from StillDown, these two operations are given priority of execution. The execution path to a control is always given priority.

StillDown is a Mac method which returns TRUE if the mouse button is down and there are no mouseDown events in the Macintosh event queue. The control on the attached match operation can be read as, “if the mouse button is not still down then go to the next case”. Otherwise execution continues with the Mac method GetMouse. This returns the current mouse position in local window coordinates. The Mac method PtInRect outputs TRUE if the mouse is within the bounds of the PButton or FALSE if it is not.

The “invert?” Local Method

“invert?” determines if the PButton should be inverted and does so if need be.

Let us descend into that local method before continuing with cases 2 and 3 of “while mouseDown”.

If the PButton is hilited and the mouse is within bounds, or if the button is not hilited and the button is outside the bounds, then it is only necessary to do nothing and pass the hilite flag through. On the other hand if the button is hilited and the mouse is out of bounds, or if the button is not hilited and the mouse is in bounds, then the two flags will not be equal to each other and the next case control will fire, causing execution of this case to terminate and execution of the next case to begin.

Because execution got to this case we know that the button needs to be inverted. We simply call the invert button method and flip the hilite flag to its opposite using the Prograph Boolean primitive not.

Back to “while mouseDown”

When the the mouse is finally released, case 2 of “while mouseDown” will be executed.

If the hilite flag is TRUE, this case is terminated and execution continues with the next case. Otherwise the hilite flag is FALSE and the button is not currently hilited. Thus the hilite flag is fed through to the output bar which is annotated with a Finish on True control. Remember that we are still inside a loop and that the loop needs to be terminated somehow. The finish control causes the case to complete and stops the looping.

In case 3 we know that the PButton is still inverted, having tested for that in case 2. invert button is called to return the PButton to normal, the hilite flag is passed through and the “finish on success” flag causes loop termination as described above.

On with the Execution!

Now we need to test our work. To do that we must first get the execution window out of the Step and Show debugging mode with which it was created. Bring the dotted background window to the foreground, and use the Clear Steps and Breaks item in the Execution menu. This will clear all single step modes and debugger break points from the method. Pressing the return key will cause the execution to continue and the window to disappear. Now click on the window with the PButton in it to bring it to the front. If you clicked within the content region of that window the menu bar should have changed to show only the File menu, as previously described.

Now, holding the mouse button down on the PButton should cause it to hilite. Drag it outside the PButton and check to see if it unhilites, and drag back in again. Then let go the mouse button. A satisfying beep, squawk or screech should occur and the button should be left unhilited. You can quit back to Prograph and save your work.

Of course if you did not get the expected behavior you may have introduced a bug. If Prograph discovers an error it will beep, open up a case window and flash the offending operation. You can then edit it on the spot and continue the execution from where you are, stepping through each case diagram one operation at a time and examining the values on roots and terminals to ensure correctness.

Conclusion

The days when a programming environment consisted of a text editor, a compiler, a linker and some sort of “symbolic” debugger are not yet behind us. But tools like Prograph are leading the way to new forms of integrated environment and new visual metaphors which will bring programming within the grasp of many for whom it is currently not feasible.

For more information

The source code for the PButton class is available from TGS Systems Ltd, 2745 Dutch Village Rd, Suite 200, Halifax, Nova Scotia, B3L 4J9, Canada, (902) 455-4446, on their bulletin board (the BBS number is (902) 455-6616). TGS also has Prograph support sections on America Online (keyword: TGS) and on CompuServe (“Go MacDev”, and check the Object-Oriented topic).

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Final Cut Pro 10.6.4 - Professional vide...
Redesigned from the ground up, Final Cut Pro combines revolutionary video editing with a powerful media organization and incredible performance to let you create at the speed of thought.... Read more
iMovie 10.3.4 - Edit personal videos and...
With a streamlined design and intuitive editing features, iMovie lets you create Hollywood-style trailers and beautiful movies like never before. Browse your video library, share favorite moments,... Read more
Motion 5.6.2 - Create and customize Fina...
Motion is designed for video editors, Motion 5 lets you customize Final Cut Pro titles, transitions, and effects. Or create your own dazzling animations in 2D or 3D space, with real-time feedback as... Read more
iMazing 2.15.8 - Complete iOS device man...
iMazing is the world’s favourite iOS device manager for Mac and PC. Millions of users every year leverage its powerful capabilities to make the most of their personal or business iPhone and iPad.... Read more
VueScan 9.7.90 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
Compressor 4.6.2 - Adds power and flexib...
Compressor adds power and flexibility to Final Cut Pro X export. Customize output settings, work faster with distributed encoding, and tap into a comprehensive set of delivery features. Features:... Read more
Capture One 15.3.2.11 - RAW workflow sof...
Capture One is a professional RAW converter offering you ultimate image quality with accurate colors and incredible detail from more than 400 high-end cameras - straight out of the box. It offers... Read more
Vivaldi 5.4.2753.28 - An advanced browse...
Vivaldi is a browser for our friends. We live in our browsers. Choose one that has the features you need, a style that fits and values you can stand by. From the look and feel, to how you interact... Read more
Parallels Desktop 18.0.0 - Run Windows a...
Parallels allows you to run Windows and Mac applications side by side. Choose your view to make Windows invisible while still using its applications, or keep the familiar Windows background and... Read more
TechTool Pro 16.0.1 - Hard drive and sys...
TechTool Pro has long been one of the foremost utilities for keeping your Mac running smoothly and efficiently. With the release of this version, it has become more proficient than ever. Main... Read more

Latest Forum Discussions

See All

Turn-Based RPG ‘Avatar: Generations’ Sof...
Square Enix London Mobile, Navigator Games, and Paramount Consumer Products just announced that the turn-based RPG Avatar: Generations based on Nickelodeon’s Avatar: The Last Airbender is soft launching this month for mobile. Avatar: Generations is... | Read more »
Tower of Fantasy launches today and brin...
Level Infinite and Hotta Studio have announced the release of their very ambitious looking shared open world MMORPG Tower of Fantasy. With its cross-platform functionality between PC and mobile, it looks to be one to roll the dice on and enjoy at... | Read more »
‘Genshin Impact’ Version 3.0 Gets a New...
After HoYoverse released Genshin Impact (Free) version 2.8 on all platforms, the company has slowly been teasing the major upcoming 3.0 update. This update features the Sumeru region with many characters. While details on the update including a... | Read more »
Out Now: ‘Tower of Fantasy’, ‘Tightrope...
Each and every day new mobile games are hitting the App Store, and so each week we put together a big old list of all the best new releases of the past seven days. Back in the day the App Store would showcase the same games for a week, and then... | Read more »
SwitchArcade Round-Up: ‘Book Quest’, ‘Cl...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for August 10th, 2022. In today’s article, we’ve got a little news about an update to a game I really like, a few new releases to summarize, and some sales to look at. A bit of a quiet... | Read more »
‘Pine Tar Poker’ is an Otherworldly Poke...
Developer BJ Malicoat, who put out the well-received and former Apple Game of the Day pick Downwordly in June of last year, is back working on another mobile game project called Pine Tar Poker, and it has caught my attention. Why? Because it’s a... | Read more »
Darkness Rises celebrates four years of...
Four years of uptime for a mobile game is akin to eternity, and this is exactly the milestone that Darkness Rises has reached. It is important for developers to keep updating to keep the game fresh, and NEXON has announced a massive anniversary... | Read more »
Keep Your Smatphone’s Case On When Using...
The original Gamevice was born as a sort of offshoot of the weird Wikipad gaming tablet/controller/hybrid thing way back in 2014. Interestingly, the first Gamevice controller for iOS only supported the iPad mini and launched in 2015, with versions... | Read more »
SwitchArcade Round-Up: A ‘Splatoon 3’ Ni...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for August 9th, 2022. In today’s article, we’ve got some news about a Splatoon 3 Nintendo Direct, a review of QUByte’s Thunderbolt Collection, a single new release summary, and the usual... | Read more »
Orangepixel’s Pacifist Survival Game ‘Re...
Back in June we learned that long-time mobile developer Orangepixel, who also makes games for PC and consoles (including the Atari VCS!), would be bringing the unique survival game Residual to mobile devices sometime this year. Originally launched... | Read more »

Price Scanner via MacPrices.net

Apple has 24-inch M1 iMacs available starting...
Apple has 24-inch M1 iMacs with M1 CPUs (8-core CPU/7-core GPU) available today in their Certified Refurbished store for $1099 shipped. Their price is $200 off standard MSRP. Each iMac is in like-new... Read more
13″ M1 MacBook Airs in stock today for $799,...
QuickShip Electronics has open-box return 13″ M1 MacBook Airs in stock and on sale for $200 off MSRP on their eBay store right now, each with free express delivery. According to QuickShip, “The item... Read more
In stock today: Mac Studio models for up to $...
Apple retailer Expercom has Mac Studio models in stock today and on sale for up to $400 off Apple’s MSRP, depending on configuration. Their prices are the lowest price available for a Mac Studio from... Read more
Mac mini with M1 CPU and 512GB of storage on...
Amazon has the M1 Mac mini with a 512GB SSD in stock today on sale for $749.99 including free shipping. Their price is $150 off Apple’s MSRP, and it’s the lowest price available for this... Read more
Need a Mac or iPad for school? Get a free App...
Apple’s Back to School promotion for 2022 continues to run through September 26, 2022. As part of this promotion, Apple will include a free $150 Apple Gift Card with the purchase of any MacBook Air,... Read more
Apple Watch SE on sale for $50 off MSRP
Amazon has Apple Watch SE GPS models on sale for $50 off MSRP for a limited time, each including free shipping. Their prices are the lowest currently available for SE Watches: – 40mm Apple Watch SE... Read more
Save $310 on a 14″ 24-core GPU M1 Max MacBook...
Save $310 on 14″ MacBook Pros with 24-core M1 Max processors at Apple (32GB RAM/1TB SSD) with these Certified Refurbished models in stock today for $2789 in Space Gray or Silver colors. Regular price... Read more
14″ M1 Pro MacBook Pros available today at Ap...
Apple has Certified Refurbished standard-configuration 14″ MacBook Pros with M1 Pro CPUs available today for up to $250 off original MSRP, starting at $1799. Each model features a new outer case,... Read more
13″ MacBook Air with M2 CPU, in Starlight, on...
Apple retailer Expercom has the new Starlight 13″ MacBook Air with an M2 CPU (8GB RAM/256GB SSD) on sale for $1135.05, shipped, through August 12, 2022. Their price is $64 off Apple’s MSRP, and it’s... Read more
14″ M1 Pro MacBook Pro with 1TB SSD on sale f...
Expercom is offering a $200 instant discount on the 14″ M1 Pro MacBook Pro with a 1TB SSD through August 12, 2022. Their discount reduces the price of this configuration to $1999 shipped — the lowest... Read more

Jobs Board

Solutions Engineering Manager - *Apple* - S...
…in our Hardware and Advanced Solutions group leading and developing our Apple technical practice to increase revenue and profitability. The ideal candidate would Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Sephora Beauty Advisor - *Apple* Blossom Ma...
Sephora Beauty Advisor - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.