TweetFollow Us on Twitter

Resize Objects
Volume Number:7
Issue Number:4
Column Tag:Jörg's Folder

Related Info: Quickdraw

Getting A Handle On Objects

By Jörg Langowski, MacTutor Editorial Board

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

“C++/MacApp - resizing objects”

As promised last month, this time we’ll start adding some code to our MacApp drawing program to change the basic shapes once they’ve been drawn. I have chosen to implement a resize operation; other functions, like changing colors and patterns, manipulating the order of objects, etc., will follow later.

We are going to use an interface similar to MacDraw, where a selected object has a number of small black squares connected with itself that can be used to change its shape. We’ll call them ‘tags’ in the following. Objects that can be circumscribed by a rectangle have eight tags: four on the corners and four on the centers of the edges. Dragging a corner tag will move the two sides of the rectangle adjacent to the corner, while dragging the edge tag will only move the side of the rectangle that contains the tag.

We’ll need code to display the tags, determine whether the mouse was clicked in one of them, and take action (track the mouse) depending on what tag it was clicked in. Of course, all operations should be undoable, but that’s almost implicit in MacApp.

Detecting the mouse click will proceed in two stages: first, we’ll check whether the mouse has been clicked in any one of the eight tags. If so, we’ll create a new command object of class TSizer, which then does the mouse tracking and track feedback. The command object determines where the mouse was clicked exactly, and the tracking and action will depend on the tag.

For the first phase - determining whether the mouse was clicked in one of the tags at all - it is convenient to create a region that consists of all the eight tags. This region is stored in a new instance variable of TBox, fTagRgn, and created when an object is selected and redrawn (see changes to the TBox::DrawShape method in listing 3). Also, the eight tags are stored individually as Rect instance variables.

The changes to the mouse down command handler are shown in listing 2. We shall now create a TSketcher, a TDragger, or a TSizer command object, depending on where the mouse was clicked - outside any object, inside a selected object, or inside one of the tags of a selected object.

In the TSizer::TrackMouse method we determine which of the eight tags was clicked in, and allow for changes in the top, bottom, left and right coordinates of the object (flags pT, pB, pL, pR). While those coordinates are continuously changed in the TrackMove phase of the TrackMouse method, the TrackFeedback method simply redraws the object rectangle in XOR mode. Undoing can be implemented very simply by remembering the old coordinates of the object.

Sounds simple? It is, and again the modifications are only to a very limited part of the total code - one of MacApp’s great advantages. We still have to add one more ‘Buzzword’ to the list of commands that appear after the Undo/Redo menu item (Listing 4), and extend the Make file a little. By now our code has grown too big to fit into one segment (compiling in Debug mode). Thus, you’ll also see how to segment a MacApp program.

I have put the code that is supposed to go into the new segment into the file TBox.cp, containing TSizer and all the Box/Shape classes. We then have to tell the MacApp builder that this file should be linked in under a different segment name. The necessary changes are shown in listing 5. We add the name of the new source file (TBox.cp) to the list of OtherInterfaces, and the corresponding object file (TBox.cp.o) to the list of OtherLinkFiles. Last, we add the dependency rule for generating the object file (also containing a comment line showing the build progress).

The drawing example will certainly still be extended over the next few months, but we’ll also take up some Forth again soon. Until then.

Listing 1: Changes to TEDrag.h

class TBox : public TObject {
public:
 Rect fLocation;
 BooleanfSelected;
 RgnHandlefTagRgn;
 Rect fTL,fTR,fBL,fBR,
 fT,fB,fL,fR;
 virtual pascal void IBox(Rect *itsLocation);
 virtual pascal void DrawShape();
 virtual pascal void NeedDiskSpace(long *data);
 virtual pascal void Read(short aRefNum);
 virtual pascal void Write(short aRefNum);
#ifdef qDebug
 virtual pascal void Fields(pascal void (*DoToField) 
 (StringPtr fieldName, Ptr fieldAddr, 
 short fieldType, void *link), void *link);
#endif
};

class TSizer : public TCommand {
public:
 TTEDocument   *fTEDocument;
 TTextView*fTextView;
 TBox   *fBox;   RectoldLocation;  RectnewLocation;      Point 
 fStart;  // mouse pressed here
 Point  fDelta;  // offset moved
 BooleanpT,pB,pL,pR; 
 // flags to indicate which coordinates to change
 pascal void ISizer(TBox *itsBox, 
 TTEDocument *itsDocument, TTextView *itsView);
 pascal struct TCommand *TrackMouse
 (TrackPhase aTrackPhase, VPoint *anchorPoint, 
 VPoint *previousPoint, VPoint *nextPoint, 
 Boolean mouseDidMove);
 pascal void TrackFeedback
 (VPoint *anchorPoint, VPoint *nextPoint,
 Boolean turnItOn, Boolean mouseDidMove);
 pascal void DoIt();
 pascal void RedoIt();
 pascal void UndoIt();
#ifdef qDebug
 virtual pascal void Fields(pascal void (*DoToField) 
 (StringPtr fieldName, Ptr fieldAddr, 
 short fieldType, void *link), void *link);
#endif
};
Listing 2: Change to TTextView::DoMouseCommand (file TEDrag.cp)
   
 if (aFindBoxStruct.myBox->fSelected)
 { if (info->theShiftKey) 
 { aFindBoxStruct.myBox->fSelected = false;
 InvalidRect (&aFindBoxStruct.myBox->fLocation);
 return inherited::DoMouseCommand
 (theMouse,info,hysteresis);   
 }
 else
 { if (PtInRgn(*theMouse,
 aFindBoxStruct.myBox->fTagRgn))
 { aSizer = new TSizer;
 FailNIL(aSizer);
 aSizer->ISizer (aFindBoxStruct.myBox,
  fTEDocument, this);
 return aSizer;   }
 else
 { aDragger = new TDragger;
 FailNIL(aDragger);
 aDragger->IDragger
 (aFindBoxStruct.myBox, fTEDocument, this);
 return aDragger;   }
 }
 }
 else
 {
 if (!info->theShiftKey) 
 { fTEDocument->ForEachShapeDo
 ((DoToObject)Deselect, &aSelectStruct); }
 aFindBoxStruct.myBox->fSelected = true;
 InvalidRect(&aFindBoxStruct.myBox-> fLocation);
 return inherited::DoMouseCommand
 (theMouse,info,hysteresis);
 }
   
Listing 3: TBox.cp
#include <UMacApp.h>
#include <UTEView.h>
#include <ToolUtils.h>
#include “TEDrag.h”

const int kBoxColor= redColor;
const int cSizer = 4001;
// Resizing support, JL 2/91
pascal void TSizer::ISizer(TBox *itsBox, 
 TTEDocument *itsDocument, TTextView *itsView)
{
 TScroller *aScroller;

 aScroller = itsView->GetScroller(true);
 ICommand(cSizer, itsDocument, itsView, aScroller);
 fTEDocument = itsDocument;
 fTextView = itsView;
 fBox = itsBox;  
 pT = false; pB = false; pL = false; pR = false;
 oldLocation = fBox->fLocation;
 newLocation = oldLocation;
}

pascal struct TCommand *TSizer::TrackMouse
 (TrackPhase aTrackPhase, VPoint *anchorPoint, 
 VPoint *previousPoint,  VPoint *nextPoint, 
 Boolean mouseDidMove)
{
 fStart = fTextView->ViewToQDPt(anchorPoint);
 
 if (aTrackPhase == trackPress) {
 if (PtInRect(fStart,&fBox->fTR)) { pT = true; pR = true; }
 else if (PtInRect(fStart,&fBox->fTL))
 { pT = true; pL = true; }
 else if (PtInRect(fStart,&fBox->fBR))
 { pB = true; pR = true; }
 else if (PtInRect(fStart,&fBox->fBL))
 { pB = true; pL = true; }
 else if (PtInRect(fStart,&fBox->fT)) { pT = true; }
 else if (PtInRect(fStart,&fBox->fB)) { pB = true; }
 else if (PtInRect(fStart,&fBox->fL)) { pL = true; }
 else if (PtInRect(fStart,&fBox->fR)) { pR = true; }
 }

 if ((aTrackPhase == trackMove) && mouseDidMove) {
 fDelta = fTextView->ViewToQDPt(nextPoint);
 SubPt(fTextView->ViewToQDPt(anchorPoint), &fDelta);
 
 if ( !((fDelta.h == 0) && (fDelta.v == 0)) ) {                
 if (pT){ newLocation.top = 
 oldLocation.top + fDelta.v;  }
 if (pB){ newLocation.bottom = 
 oldLocation.bottom + fDelta.v; }
 if (pL){ newLocation.left = 
 oldLocation.left + fDelta.h; }
 if (pR){ newLocation.right = 
 oldLocation.right + fDelta.h; }
 }
 }

 if ((aTrackPhase == trackRelease) && mouseDidMove) {
 fDelta = fTextView->ViewToQDPt(nextPoint);
 SubPt(fTextView->ViewToQDPt(anchorPoint), &fDelta);
 if ((fDelta.h == 0) && (fDelta.v == 0))
 { return gNoChanges; }
 fBox->fLocation = newLocation;
 }
 return this;
}

pascal void TSizer::TrackFeedback
 (VPoint *anchorPoint, VPoint *nextPoint,
 Boolean turnItOn, Boolean mouseDidMove)
{
 PenState oldState;
 
 if (mouseDidMove) {
 GetPenState(&oldState);
 PenNormal();
 PenMode(patXor);
 FrameRect(&newLocation);
 SetPenState(&oldState);
 }
}

pascal void TSizer::DoIt()
{fTextView->InvalidRect(&newLocation);
 fTextView->InvalidRect(&oldLocation);   }

pascal void TSizer::RedoIt()  
{  fBox->fLocation = newLocation; DoIt();    }

pascal void TSizer::UndoIt()
{fBox->fLocation = oldLocation; DoIt();      }

#ifdef qDebug
pascal void TSizer::Fields(pascal void (*DoToField) 
 (StringPtr fieldName, Ptr fieldAddr, 
 short fieldType, void *link), void *link)
{
 DoToField(“\pTSizer”, nil, bClass, link);
 DoToField(“\pfTEDocument”, 
 (Ptr) &fTEDocument, bObject, link);
 DoToField(“\pfTextView”, (Ptr) &fTextView, bObject, link);
 DoToField(“\pfBox”, (Ptr) &fBox, bObject, link);
 DoToField(“\poldLocation”, (Ptr) &oldLocation, bRect, link);
 DoToField(“\pnewLocation”, (Ptr) &newLocation, bRect, link);
 DoToField(“\pfStart”, (Ptr) &fStart, bPoint, link);
 DoToField(“\pfDelta”, (Ptr) &fDelta, bPoint, link);
 DoToField(“\ppT”, (Ptr) &pT, bBoolean, link);
 DoToField(“\ppB”, (Ptr) &pB, bBoolean, link);
 DoToField(“\ppL”, (Ptr) &pL, bBoolean, link);
 DoToField(“\ppR”, (Ptr) &pR, bBoolean, link);
 inherited::Fields(DoToField, link);
}
#endif

pascal void TBox::IBox(Rect *itsLocation)
 {    fLocation = *itsLocation; fSelected = false; }

pascal void TBox::DrawShape()
{
 if (fSelected) {
 short halfH, halfV;
 
 halfH = (fLocation.right-fLocation.left)/2;
 halfV = (fLocation.bottom-fLocation.top)/2;
 
 PenSize (1,1);
 ForeColor(blackColor);
 FrameRect(&fLocation);
 
 fTagRgn = MakeNewRgn();
 OpenRgn();
 
 fTL.top = fLocation.top;
 fTL.left = fLocation.left;
 fTL.bottom = fTL.top + 4;
 fTL.right = fTL.left + 4;
 FrameRect(&fTL);
 
 fT.top = fLocation.top;
 fT.bottom = fT.top + 4;
 fT.left = fLocation.left + halfH - 2;
 fT.right = fT.left + 4;
 FrameRect(&fT);
 
 fTR.top = fLocation.top;
 fTR.bottom = fTR.top + 4;
 fTR.right = fLocation.right;
 fTR.left = fTR.right - 4;
 FrameRect(&fTR);
 
 fBL.bottom = fLocation.bottom;
 fBL.top = fBL.bottom - 4;
 fBL.left = fLocation.left;
 fBL.right = fBL.left + 4;
 FrameRect(&fBL);
 
 fB.bottom = fLocation.bottom;
 fB.top = fB.bottom - 4;
 fB.left = fLocation.left + halfH - 2;
 fB.right = fB.left + 4;
 FrameRect(&fB);
 
 fBR.bottom = fLocation.bottom;
 fBR.top = fBR.bottom - 4;
 fBR.right = fLocation.right;
 fBR.left = fBR.right - 4;
 FrameRect(&fBR);
 
 fL.top = fLocation.top + halfV - 2;
 fL.bottom = fL.top + 4;
 fL.left = fLocation.left;
 fL.right = fL.left + 4;
 FrameRect(&fL);
 
 fR.top = fLocation.top + halfV - 2;
 fR.bottom = fR.top + 4;
 fR.right = fLocation.right;
 fR.left = fR.right - 4;
 FrameRect(&fR);
 
 CloseRgn(fTagRgn);
 FillRgn(fTagRgn,qd.black);
 ForeColor(kBoxColor);  }
}
   the rest of the file (TShape and following definitions) stays unchanged 
  
Listing 4: Change to TEDrag.r

#define cSizer   4001
resource ‘cmnu’ (128) {
 128, textMenuProc, allEnabled, enabled, “Buzzwords”,          /* these 
words appear after Undo in the Edit menu */
  {
 “Page Setup Change”, noIcon, noKey, 
 noMark, plain, cChangePrinterStyle;
 “Typing”, noIcon, noKey, noMark, plain, cTyping;
 “Drawing”,  noIcon, noKey, 
 noMark, plain, cDrawBox;
 “Dragging”,  noIcon, noKey, 
 noMark, plain, cDragBox;
 “Resize”,  noIcon, noKey, noMark, plain, cSizer
 }
};
Listing 5: TEDrag.MAMake
AppName = TEDrag
OtherInterfaces =  
 “{SrcApp}TBox.cp”
OtherLinkFiles = 
 “{ObjApp}TBox.cp.o”
“{ObjApp}TBox.cp.o”ƒ 
 “{SrcApp}TBox.cp” 
 “{SrcApp}TEDrag.MAMake” 
  {MacAppIntf} 
  {BuildingBlocksIntf}
 {MAEcho} {EchoOptions} “Compiling:     TBox.cp”
 {MACPlus} 
 {CPlusOptions} 
 -s TBox 
 -i “{SrcApp}” 
 -i “{MACIncludes}” 
 -o “{ObjApp}TBox.cp.o” 
 “{SrcApp}TBox.cp”
OtherRsrcFiles = 
 “{MAObj}Printing.rsrc” 
 “TEOther.rsrc”

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Vienna 3.0.6 :5eaf312: - RSS and Atom ne...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
Kodi 15.1.rc1 - Powerful media center to...
Kodi (was XBMC) is an award-winning free and open-source (GPL) software media player and entertainment hub that can be installed on Linux, OS X, Windows, iOS, and Android, featuring a 10-foot user... Read more
Bookends 12.5.8 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Access the power of Bookends directly from Mellel, Nisus Writer Pro, or MS Word (... Read more
Chromium 44.0.2403.125 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. Version 44.0.2403.125: This release contains a number... Read more
iMazing 1.2.2 - Complete iOS device mana...
iMazing (was DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and from... Read more
Audio Hijack 3.2.0 - Record and enhance...
Audio Hijack (was Audio Hijack Pro) drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio... Read more
FontExplorer X Pro 5.0.1 - Font manageme...
FontExplorer X Pro is optimized for professional use; it's the solution that gives you the power you need to manage all your fonts. Now you can more easily manage, activate and organize your... Read more
Calcbot 1.0.2 - Intelligent calculator a...
Calcbot is an intelligent calculator and unit converter for the rest of us. Featuring an easy-to-read history tape, expression view, intuitive conversion, and much more! Features History Tape -... Read more
MTR 5.0.0.1 - The Mac's oldest and...
MTR (was MacTheRipper)--the Mac's oldest and smartest DVD-backup app--is now updated to version 5.001 MTR -- the complete toolbox, not a one-trick, point-and-click extractor. MTR is intended for... Read more
LibreOffice 4.4.5.2 - Free, open-source...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more

Card King: Dragon Wars - Tips, Tricks an...
[Read more] | Read more »
Pac-Man Championship Edition DX has brou...
Bandai Namco has released Pac-Man Championship Edition DX on iOS and Android, which features the classic arcade gameplay that we've all grown to love. Pac-Man Championship Edition DX can be enjoyed in much shorter bursts than the arcade versions... | Read more »
Cosmonautica (Games)
Cosmonautica 1.1 Device: iOS Universal Category: Games Price: $6.99, Version: 1.1 (iTunes) Description: Cast off! Are you ready for some hilarious adventures in outer space? | Read more »
Rescue humanity from a Demon horde in An...
Angel Stone is Fincon's follow up to the massively successful Hello Hero and is out now on iOS and Android. You play as a member of The Resistance, a group of mighty human warriors who have risen up in defiance of the Demon horde threatening to... | Read more »
Gallery Doctor (Photography)
Gallery Doctor 1.0 Device: iOS iPhone Category: Photography Price: $2.99, Version: 1.0 (iTunes) Description: Free up valuable iCloud and iPhone storage with Gallery Doctor, the only iPhone cleaner that automatically identifies the... | Read more »
You Against Me (Games)
You Against Me 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: A simple game… You. Me. Claim, steal, lock, score, win! | Read more »
Yep, it's True - Angry Birds 2 is O...
The not exactly rumors were true and the birds are back. Angry Birds 2 has come to the App Store and the world will... well I suppose it'll still be the same, but now we have more bird-flinging options! [Read more] | Read more »
You Could Design Your Own Card for Chain...
If you've ever wanted to create your own item, weapon, trap, or even monster for Chainsaw Warrior: Lords of the Night, this is your chance. Auroch Digital is currently holding a contest so that fans can fight to the death (not really) to see which... | Read more »
Bitcoin Billionaire is Going Back in Tim...
If you thought you managed to buy everything there is to buy in Bitcoin Billionaire and make all the money, well you though wrong. Those of you who made it far enough might remember investing in time travel - and it looks like that investment is... | Read more »
Domino Drop (Games)
Domino Drop 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Domino Drop is a delightful new puzzle game with dominos and gravity!Learn how to play it in a minute, master it day by day.Your... | Read more »

Price Scanner via MacPrices.net

Back-to-School with Tablet and Smartphone Acc...
Belkin helps you prepare for the coming school year with a wide variety of the latest mobile and tablet accessories to outfit both grade school and college students. The line-up includes charging... Read more
11-inch MacBook Airs on sale for $100 off MSR...
Best Buy has 11-inch MacBook Airs on sale for $100 off MSRP. Choose free shipping or free local store pickup (if available). Sale prices for online orders only, in-store prices may vary: - 11″ 1.6GHz... Read more
iPad Air 2 on sale for up to $100 off MSRP
Best Buy has iPad Air 2s on sale for up to $100 off MSRP on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale prices available for online... Read more
Sale! 13-inch MacBook Pros on sale for $100 o...
B&H Photo has 13″ MacBook Pros on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.5GHz/500GB MacBook Pro: $999.99 save $100 - 13″ 2.7GHz/128GB Retina... Read more
Sale! Save $100 on 13-inch MacBook Airs this...
B&H Photo has the 13″ 1.6GHz/128GB MacBook Air on sale for $899.99 including free shipping plus NY tax only. Their price is $100 off MSRP, and it’s the lowest price available for this model.... Read more
Worldwide Tablet Market Decline Continues, Ap...
The worldwide tablet market declined -7.0% year-over-year in the second quarter of 2015 (2Q15) with shipments totaling 44.7 million units according to preliminary data from the International Data... Read more
TP-LINK TL-PA8030P KIT Powerline Featuring Ho...
Consumer and business networking products provider TP-LINK is now shipping its TL-PA8030P KIT AV1200 3-Port Gigabit Passthrough Powerline Starter Kit that expands your home’s network over its... Read more
Apple refurbished iPad Air 2s available for u...
The Apple Store has Apple Certified Refurbished iPad Air 2s available for up to $140 off the price of new models. Apple’s one-year warranty is included with each model, and shipping is free: - 128GB... Read more
Updated Apple iPad Price Trackers
We’ve updated our iPad Air Price Tracker and our iPad mini Price Tracker with the latest information on prices and availability from Apple and other resellers. Read more
Apple refurbished 2014 13-inch 128GB MacBook...
The Apple Store has Apple Certified Refurbished 2014 13″ MacBook Airs available starting at $759. An Apple one-year warranty is included with each MacBook, and shipping is free: - 13″ 1.4GHz/128GB... Read more

Jobs Board

*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
Infrastructure Engineer - *Apple* /Mac - Hil...
Infrastructure Engineer - Apple /Mac Job Code: 1608 # of openings: 1 Description Our fortune 500 client is looking to hire an experienced Infrastructure Engineer to join Read more
Executive Administrative Assistant, *Apple*...
…supporting presentation development for senior leadership. * User experience with Apple hardware and software is preferred. Additional Requirements The following list Read more
*Apple* Bus Company is now hirin - Apple Bus...
Apple Bus Company is now hiring school bus drivers in the Pettis County area. Class B CDL preferred. Free training provided. No nights or weekends required. Flexible Read more
*Apple* Certified Mac Technician - Updated 6...
…and friendly, hands-on technical support to customers troubleshooting and repairing Apple /Mac products with courtesy, speed and skill. Use your problem-solving skills Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.