Quadratic Plotters 2
Volume Number: | | 5
|
Issue Number: | | 9
|
Column Tag: | | MacApp Workshop
|
A Tale of Two Quadratic Plotters, Part II
By Carl Nelson, Chuck McMath, Hillsborough, VA
Another point of view
When I started my efforts, I had to bring the program into the MPW environment, after all I started with someone elses code and wanted to cut and paste as much as I could. The first thing I did was run the source code through the MPW tool MapObjects. This handy tool finds all Pascal UNITs defined in the files you give it to digest, then it goes about finding all PROCEDUREs, FUNCTIONs and Objects that are defined. As it encounters the source code it remembers where (file and offset) it saw implementations of the procedures, then it writes out a database (called an ObjectMap) which can then be used by the Browser Desk Accessory to find and view procedures, functions and objects. Essentially you get a list of all Pascal UNITS, in alphabetical order, seen by MapObjects and for every by Pascal UNIT you can see, in alphabetical order, all PROCEDURES and FUNCTIONS contained in the UNIT. You can then click on the name of a PROCEDURE and the DA fetches it for you to view. It is a read-only browser, but you can cut from the displayed text and paste it into your MPW file. (I also pass the latest MPW interfaces through MapObjects. This way I always have them online when I need to cut and paste a Toolbox call.)
Displayed below is the output from doing a MapObjects -hvsm on the original MacTutor Code. Note that where a line has two items on it, the second item is the name of the file containing that unit:
Program
QuadraticPlotter plotter
QuadraticPlotter-Private plotter
main
initRects
doUpdates
doMulti
doMouse
doKeyDowns
doActivates
crash
MainEventLoop
InitMyWindow
InitMyMenus
InitMac
Unit
PlotGlobals PlotGlobals
MyFileStuff myFileStuff
doSaveAs
doSave
MyPlotStuff myPlotStuff
doQuit
doMenubar
doGrow
doDrag
doContent
doAbout
Misc Misc
doMessage
MyPrintStuff myPrintStuff
doPrint
doPageSet
MyPrintStuff-Private myPrintStuff
PrintMe
solve solve
solveit
quad
doPlot
PrQDStuff
solve-Private solve
positivecalc
negativecalc
doDialog
PlotMe
The Browser turns out to be very helpful in understanding the MacTutor sources. I am not a veteran of previous MacTutor code so I did not know where Dave had decided to hide various parts of the code. I had expected that Daves code would have some organizing principles that he used to decide where to put PROCEDURES and FUNCTIONS. The article pointed the way but you can also see it from the MapObjects output. The main program is contained in the file plotter. Code to initialize things was found in the Init routines in the main file plotter. What struck me was the pragmatic organization of the code. The principles that organized it seemed straightforward and general enough but I would never have guessed where the functionality would actually be found. I had forgotten how much my familiarity with MacApp and its architecture caused me to make certain assumptions when looking at someone elses code.
For example, when I first received a copy of Chucks code I wondered if he had taken the time to implement the full page printing option. Knowing MacApp, I knew he would have created a DoSetupMenus and a DoMenuCommand to handle the functionality. So to check his code out I used the MPW search command to find all occurrences of DoSetupMenus in the .inc1.p file he sent and sure enough, I found he had two DoSetupMenus, one in TQPlotApplication and the other in TQPlotView. Selecting the line with TQPlotView yielded exactly what I wanted to know, it used a field (fOnePage) to place a checkmark beside a couple of menu entries that had associated command names of cPrintWS and cPrintPS which I deduced were probably print window size and print page size which corresponded to the original MacTutor code. Having such strong notions of where things are (and ought to be) makes it easy to maintain and extend someone elses source code. [Chucks note: the reason Carl was able to find that section of my code so easily was partially because of the MacApp pact I signed when I converted the code to MacApp -- I agreed to place the code (actually I had very few other choices, being a good MacApp citizen and all) which deals with menu selections in the method DoMenuCommand, and Carl knows this.]
In terms of external design features, the original plot program had two things that caught my attention. First was that the PICT was always drawn to fill the window and the second was that a modal dialog was put up to get the parameters for the equation. I thought that always filling the window was a bit odd but, hey, Im not really an engineer who plots quadratics all the time (if ever) so I felt that should be left alone. I actually had to do extra work to make the program behave this way. In the MacApp framework the simplest case would have been to setup a fixed size page or view area and then let MacApp scroll the image around for you. The modal dialog was probably an expedient design; there has to be a better user interface. I thought that it would be far better if the plot parameters could be entered in the plot window. My design was simple: put all the fields from the modal dialog into a panel to the side of the plot area, let the user click and type new parameters at any time in a modeless fashion, and then let the user choose PLOT from the menu or press the ENTER key to cause the plot to occur. This simple design change allows multiple windows with their plots and parameters that created them to be showing at the same time.
Figure 1.
The original program only allowed the choice of 8 colors for the plot. I thought as an example program that it should use the new Palette manger and let the user color as many parts of the plot with any color. Also I thought it would be nice to allow for the selection of fonts and typestyles using the hierarchical menus. Besides, I could easily cut and paste all these features from the MacApp samples.
In starting my port of the code I was going to use an external data structure to hold the pertinent data. After I started the design it became obvious that if I did a little bit of encapsulation it would be a good example of the right path to follow and clearly show the advantages of using Objects just like in Chucks program; I gave the original plot programs data to the appropriate object to manage.
As Chuck pointed out, there are always three methods you will override: TApplication.DoMakeDocument, which creates the appropriate type of Document object; TDocument.DoMakeViews which creates the appropriate type of View and window objects and finally TView.Draw which Draws the contents of a view in your window or on the page.
I had to declare a Document type (TPlotDoc) that DoMakeDocument could bring into existence. This document would hold the plots we would be writing to disk. The files created by this document would be readable with MacDraw and able to be placed into PageMaker. In order to read back these files I implemented a DoRead for TPlotDoc. Granted, it is a simple minded effort but it shows where it should be done. To properly implement writing and reading the plot parameters should also be written and read back.
When a document is created its DoMakeViews method is called to create the views that will display the data in the document. In MacApp 2.0 you can create views by doing a NEW for each view component and setting up the data structures, or you can (preferably) create resources that describe your views and let MacApp read them, create the objects and fill in their data structures. These resources are best created using Apples ViewEdit. ViewEdit knows about MacApp view resources and lets you build and arrange on screen the view components that will make up your displays. It is indispensible in creating Applications with MacApp 2.0.
In looking at the view hierarchy, we start with a window which is handled by a standard TWindow. In the window is a dialog handled by TPlotDialog. The dialog contains two display clusters and a scroller. The two clusters contain StaticText and NumberText view items that are used for collecting the equation coefficients and the plot parameters. The scroller contains the plot view which is handled by a TPlotView. The plot view contains a subview for holding the solution text box. It is handled by a TSolutionView.
This hierarchy of views are brought into existence by TPlotDocs DoMakeViews call to NewTemplateWindow. As each component of the view hierarchy is brought in existence, the associated object which will handle it is found and created by DoCreateViews.
For the TStaticText and TNumberText views MacApp handles all the display and collection of keystrokes. MacApp 2.0ß8 does not have facilities for handling NumberViews with Real numbers, an oversight in the rush to get MacApp 2.0 out the door. Calvin Cock wrote an article (and contributed the code and resources) for publication in the Dec 88 Frameworks describing the a new view called TExtendedText which handles real numbers (plug: join the MacApp Developers Association and receive Frameworks). Instead of reinventing the wheel, I used Calvins ExtendedText Views in the Clusters.
Here is a summary of the view hierarchy which produced the window in Figure 1:
In what I would call a fairly straightforward MacApp approach, TPlotDoc holds the parameters for the plot and TPlotDialog holds the PicHandle generated from the original data structure and does the display of the PICT. TPlotView and TSolutionView do all the work of actually drawing the PICT. Further work could be done on encapsulating and distributing the plotting and display. In particular, PRQDStuff from the original was a fairly large routine that did all the drawing work. I thought it might be proper to split it apart into a controlling object and objects that drew parts of plot. Not to go overboard, but to illustrate the point, I chose to have TPlotDialog create the wrapper and have it call the appropriate component parts that composed the PICT. TPlotDialog sets up the PICT and asks the other objects that it knows draw into it. It should be possible with the framework I have provided to move each AXIS and its labeling into separate views that can be setup independently.
The current design does not utilize any of the MacApp framework to do interactive graphing. If the design of the program changed not to include re-scaling the PICT to the window, it would be possible to create an interaction with the PlotView. For example, you could grab the plot and move it around to show how the coefficients vary.
Given how easy it is to create multiple windows and documents, it would be easy to create plot types and custom windows for different equations. To do this would require that you create new types of plot and view objects then override MacApps OpenNew method to create the desired new kind of plot document and window.
As Chuck stated MacApp provides a command mechanism for undo and redo. If you look at the menu handling code for changing the plot color and text you will see how I have implemented Undo/Redo by saving and restoring the plot characteristics. I did not go all the way by invaliding the Plot and forcing a redraw instead I, like the Daves, wait until the next plot is drawn. If you look at TPlotDialog.DoKeyCommand you will see how easy it would be to have TPlotDoc.DoMenuCommand force a redraw.
Analysis
Now that we have each discussed our programs, we need to sit back a little and see just what we got out of MacApp. While Carls version is obviously an improvement given the number of features he added, the benefits of Chucks version are not so obvious. So Chuck re-takes the floor to convince you hes done a good job.
How much time do we spend doing things?
With all of the preceding discussion of my objects, it may seem that we are doing a lot of work in what is admittedly a simple application. Lets see if this is the case. I have analyzed the original and my code to see what percentage of code is used for different functions. This analysis is not perfect in that the original and new versions were written by different people, and therefore it does not allow for different programming styles, but still, the end application is the same (or as similar as a MacApp and non-MacApp application can be), so we can get an idea of where we spent our time. I split the source code into five different categories:
user interface: the Macintosh look -- windows, menu setup and enabling, the generic Mac portion. What code was necessary to make the application look like a Macintosh application? Note that this does not include the code to actually accomplish anything; thats in the next section.
interaction: the portion of the code that handles any user interaction & event processing. Anything that was written to handle interaction between the user and the application was assigned here.
input/output routines: any code involved with actually reading or writing data to the disk. This portion also includes code used to print the window, since I considered that an output operation.
program processing: this portion of code is anything that needed to be written to calculate or determine anything. This code does not have any corresponding on-screen elements.
initialization and other: this category was used for all pieces of code that I couldnt assign anywhere else.
Chart 1 shows for each category: the number of lines of code written for each version, and Chart 2 the percent of the total code that each section represents (comments and blank lines were removed before the count was made, so this is only counting executable code; 1405 for the original and 705 for MacApp).
Chart 1: Lines of Code comparison: Original vs. MacApp
The first difference that should jump out at you is the number of lines of code written. The MacApp version has half the number of lines as the non-MacApp version. Not only are there fewer lines, but the MacApp version has more features than the original version -- it allows multiple windows on the screen and scrolls the window contents, to name two. In addition, the MacApp feature follows Apples user interface guidelines more closely in the page size/window size feature of the plot. In the original version, selecting window size changes the printed output, but does not change the display in the window -- violating the WYSIWYG principle (What You See Is What You Get). So theres another area in which the MacApp program outperforms the original one. Still another area in which the MacApp version improves on the original is in menu handling. The original version has the Edit menu always enabled, even though those menu items do not apply to anything displayed in the window; you can also erroneously try to save or print before you have a plot window on the screen. Again, these operations violate the user interface guidelines -- only appropriate menu items should be enabled. Yet the MacApp version does enable all of its menu items correctly. Why? Because of the design of MacApp.
Its interesting to compare how time was spent in creating the two versions (assuming that the code was written at a constant rate. I know this is not an entirely rational assumption, but its all we have to go on). Ive been talking about how MacApp helps you by implementing the standard user interface elements, but looking at the chart you see that the MacApp program has four times as much user interface code (relatively speaking). Does this mean that I was lying? I sure hope not! The reason for so much user interface code in the MacApp version is that there is a fixed amount of overhead associated with handling menu, mouse, and key events. This overhead is in the form of procedures which must be overridden to provide for the user interface processing. In addition, each object which handles these events must override the appropriate methods to provide the processing. Writing the code for all of these overrides adds up. However, once the procedures are overridden, adding more functionality to the processing is simple and does not require much more code. On the other hand, look at the amount of code we wrote to deal with interaction -- the MacApp implement spent only half as much time implementing its interaction code. This is because we build upon the foundation that MacApp provides, and only have to add code to support the extra functionality we wish to provide. MacApp takes care of the normal interaction.
Chart 2: Percent of Code: Original vs. MacApp
This application is somewhat unusual in that the amount of pure processing code is rather small, although its interesting that the relative amount of processing code is constant. One last thing to note is the amount of code in the Other category. As I categorized the source code for the MacApp version, I realized that much of the code fell into this category. Thats because MacApp programs spend a lot of time initializing objects, creating windows and views and documents, and doing a lot of things that are difficult to categorize.
Chart 3 shows the amount of code that came directly from the original version to the MacApp version. The first column is the number of lines of code that was directly cut and pasted from the old version to the new. The second column is the total number of lines in the new category. The third column shows the percentage of each category that the old code makes up. This chart is instructive in that it shows how much of your non MacApp program you will be able to reuse. It shouldnt be surprising that none of the interaction or user interface code was transferable; its a little more surprising that none of the other code was applicable. If you think about it, however, the MacApp other category is made up of code which is pretty specific to MacApp -- object creation and initialization, and the object definitions. This code could not have come from the original program.
# Lines Taken Total in New % of New
Input/Output 181 211 86
Interaction 0 108 0
Other 0 221 0
Processing 48 48 100
User Interface 0 117 0
Totals 229 705 N/A
Chart 3: Code requiring no conversion
As you can see, all of the processing code used in the MacApp program came directly from the original version. This should give some weight to my assertion that in a MacApp program you need to concentrate on the unique portion of your application -- for indeed, in the plotter application, the processing is the unique portion. And note also that most of the input/output routines came directly from the original version. Most of this code is related to creating and printing the PICT, and of course remains the same no matter whether youre using MacApp or not.
The bottom line here, though, is that the MacApp version only required 50% as much code as the original version; and fully one-third of that code was lifted directly from the original, which means that the MacApp version only had around 500 new lines of code -- one third as much as the original. And this does not yield a program that is crippled or partially functional, it yields a program that conforms to the user interface guidelines, is fully functional (within its design), and is a good bet to run on future Macintosh architectures (not to mention A/UX). This is the big win we get from MacApp: not something for nothing, but more results for less work. Sure, you have to change your thinking, but all I can say is this: look at the bottom line.
Conclusion
So there you have it -- two views of a MacApp conversion effort, from two slightly different viewpoints. Although the two MacApp programs may seem quite different, they are much more similar to each other than either is to the original effort. If Carl and I swapped our two MacApp programs and each had to add a feature to them, we would be able to much more easily than if we were to try the same on the original program. All MacApp programs share a structure, an organization; different programs do similar things in the same place. Reusing code from one MacApp program to another is increased. You dont have to spend time searching for the procedure or function you want -- you will know where to find it.
We hope you have some idea of the benefits of MacApp and that youll not only get more done, but youll get it done more quickly (once you become a MacApp citizen), and your final product will be a real professional job. MacApp is the wave of the future -- catch it today! [Aw Come-on Chuck, knock it off.]
UPlot.p Plot UNIT FILE
{[a-,body+,h,o=100,r+,rec+, t=4,u+,#+,j=20/57/1$,n+]}
{ The above is the official MacApp PasMat Style statement.What you dont
use pasmat to make all your source code conform to your companys (or
personal) standard for source code style? }
{Copyright © 1986-1988 Apple Computer, Inc.
All rights reserved.}
{Copyright © 1989 by Software Architects, Inc.
All rights reserved.}
{Portions Copyright © 1988 MacTutor
All rights reserved.}
{[f-]}
(*
This is a very small sample application which uses concepts and program
fragments presented in the February 1988 MacTutor Plot Article.
By looking at this program you may be able to gain a better understanding
of how to cast a conventional program into the MacApp Application Framework
or (Class structure depending upon whose jargon you wish to use).
In the tradition of MacApp it defines the basic three Class (object)
overrides:
TPlotApplication.DoMakeDocument -- Launches appropriate type of Document
object.
TPlotDoc.DoMakeViews -- Launches appropriate type View and window objects.
TPlotDialog.Draw -- Calls it sub components to draw the contents of
a view.
TPlotView-- To actually plot the thing
TSolveView -- To draw the solution text box
In addition it defines commands unique to the plot program. See the text
of the accompaning article for detials.
*)
{[f+]}
UNIT UPlot;
INTERFACE
USES
{ MacApp - this includes all of the things
necessary from the MacApp Library }
UMacApp,
{ Building Blocks }
UDialog, UPrinting, UExtendedText,
{ Implementation Use }
SANE, ToolUtils, Fonts, Resources,
Script, PickerIntf, Packages;
CONST
kSignature = Plot;
{ Application signature}
kFileType= PICT;
{ File-type code used for document files
created by this application}
kPlotDialog= 1010;
{ MacApp uses a very useful technique for seperating menu item numbering
from what you want done by chosing a menu item. See MacApp manual pggs
xxx-xx for full details. Work is done in MacApp with commands. Each
command is assigned a unique number. For example Save is 30 and SaveAs
is 32. Numbers below 1200 are reserved for MacApp. In this Application
we have chosen a command numbering scheme that makes life easy:
Application Commands= 1400
Font styles = 2000
Font sizes = 2100
Font just = 2200
Font fonts = 2300
Hierarchical Menus= 2400
Plot colors= 2500
}
{ the command to cause a plot to happen }
cPlotIt= 1401;
{ Command numbers for typestyle attributes }
cPlainText = 2001;
cBold = 2002;
cItalic = 2003;
cUnderline = 2004;
cOutline = 2005;
cShadow = 2006;
cCondense= 2007;
cExtend = 2008;
{ Command numbers for font-size commands }
cSizeChange = 2100;
cSizeBase= 2100;
cSizeMin = 2109;
cSizeMax = 2124;
{ 2101-2197 reserved for font sizes 1-97 pts. }
cSizeGrow= 2198;
cSizeShrink = 2199;
{ Command numbers cover other stylistic changes }
cJustChange = 2200;
cJustLeft= 2201;
cJustCenter = 2202;
cJustRight = 2203;
cFontChange = 2300;
{ Command numbers for the hierarchial menu }
cStyle = 2401;
cSize = 2402;
cFont = 2403;
cColor = 2404;
{ Command numbers for changing colors }
cColorChange = 2500;
cColorText = 2501;
cColorBackground= 2502;
cColorGraph= 2503;
cColorAxis = 2504;
{ Constant for amount to relative
size text selection }
kRelSizeAmount = 4;
{ Constants for the prompts string list }
kPromptsRsrcID = 1001;
kColTextPrompt = 1;
kColBackPrompt = 2;
kColGraphPrompt = 3;
kColAxisPrompt = 4;
{ Menu numbers }
mFont = 10;
{ Menus displayed on hier. menu system }
kHierDisplayedMBar= 131;
{ Menus displayed on non-hier. system }
kNonHierDisplayedMBar = 128;
{ Offset added to non-hier menu cmds to get }
kHierMenuOffset = 1000;
{ view resource for default values }
kViewRsrcID = 1005;
{ PICT comments for our plot and text box }
{selected MacDraw comments}
picDwgBeg = 130;
picDwgEnd= 131;
picGrpBeg = 140;
picGrpEnd = 141;
TextBegin = 150;
TextEnd = 151;
StringBegin= 151;
StringEnd = 153;
TextCenter = 154;
{postscript comments}
SetLineWidth = 182;
PostScriptBegin = 190;
TextIsPostscript = 194;
PostScriptEnd = 191;
{ The size of a MacDraw Header }
kHeaderSize = 512;
TYPE
QuadraticType = (NotSolved, RealRoots,
SingleSolution, ComplexRoot);
{specifications of text display}
PlotSpecs= RECORD
theTextFont: Str255;
theFontNum:INTEGER;
theTextFace: Style;
theTextSize: INTEGER;
theJustification:INTEGER; { text }
theTextColor: RGBColor; { label color }
theGraphColor: RGBColor;
theAxisColor: RGBColor;
theBackColor: RGBColor;
END;
PlotSpecsPtr = ^PlotSpecs;
PlotSpecsHdl = ^PlotSpecsPtr;
{ Object Definitions }
{------------------------------------}
TPlotApplication = OBJECT (TApplication)
{ Initialize application and globals. }
PROCEDURE TPlotApplication.IPlotApplication(
itsMainFileType: OSType);
{ Launches a TPlotDocument }
FUNCTION TPlotApplication.DoMakeDocument(
itsCmdNumber: cmdNumber): TDocument;
OVERRIDE;
PROCEDURE TPlotApplication.IdentifySoftware;
OVERRIDE;
PROCEDURE TPlotApplication.Fields(
PROCEDURE DoToField(fieldName: Str255;
fieldAddr: Ptr;
fieldType:INTEGER));
OVERRIDE;
END; { TPlotApplication }
{------------------------------------}
TPlotDoc = OBJECT (TDocument)
fPlotDialog: TPlotDialog;
fPlotSpecs : PlotSpecs;
fOldPlot : PicHandle;
{ coefficients to our quadratic equation }
faParam: Real;
fbParam : Real;
fcParam: Real;
{ plot display parameters }
fstepParam : Real;
fxParam: INTEGER;
fyParam : INTEGER;
{ the solutions to our quadratic }
f1stRoot : Real;
f2ndRoot : Real;
fRootType: QuadraticType;
{ setup for the document to hold the plot }
PROCEDURE TPlotDoc.IPlotDocument;
{ For new doc or revert initial state }
PROCEDURE TPlotDoc.DoInitialState; OVERRIDE;
{ Generate command to change Look of a plot }
FUNCTION TPlotDoc.DoMakePStyleCmd( itsStyle:PlotSpecsPtr; itsCmdNumber:CmdNumber):
TPStyleCmd;
{ create all the views needed for document }
PROCEDURE TPlotDoc.DoMakeViews(forPrinting: BOOLEAN); OVERRIDE;
{ calculater how much disk space this
document will need }
PROCEDURE TPlotDoc.DoNeedDiskSpace(
VAR dataForkBytes, rsrcForkBytes: LONGINT);
OVERRIDE;
{ read the data for this document }
PROCEDURE TPlotDoc.DoRead(
aRefNum: INTEGER; rsrcExists,
forPrinting: BOOLEAN); OVERRIDE;
{ write the data for this document }
PROCEDURE TPlotDoc.DoWrite(aRefNum: INTEGER;
makingCopy: BOOLEAN); OVERRIDE;
{ given a Menu choice handle or pass it on }
FUNCTION TPlotDoc.DoMenuCommand(
aCmdNumber: cmdNumber): TCommand;
OVERRIDE;
{ setup the menus for the document }
PROCEDURE TPlotDoc.DoSetupMenus; OVERRIDE;
{ given the parameters of our
document calculate a solution }
PROCEDURE TPlotDoc.SolveQuadratic;
PROCEDURE TPlotDoc.ChangeBackColor(
newColor: RGBColor);
{$IFC qDebug}
PROCEDURE TPlotDoc.Fields(
PROCEDURE DoToField(
fieldName: Str255;
fieldAddr: Ptr;
fieldType: INTEGER));
OVERRIDE;
{$ENDC}
END; { TPlotDoc }
TPlotView= OBJECT (TView)
fPlotDoc : TPlotDoc;
{ Add to the pict we will draw on
the screen or printed page }
PROCEDURE TPlotView.AddToPict(picRect:Rect);
{ A convenience routine }
PROCEDURE TPlotView.GetQDFrame(
VAR frameRect:Rect);
{ The design says the plot fills the
window, therefore when we are
resized we must invalidate ourselves}
PROCEDURE TPlotView.Resize(width,
height: VCoordinate; invalidate: BOOLEAN);
OVERRIDE;
END;
TSolutionView = OBJECT (TView)
fPlotDoc : TPlotDoc;
fSolveRect : Rect;
{ Add to pict we will draw on the screen or printed page }
PROCEDURE TSolutionView.AddToPict(picRect:Rect);
END;
TPlotDialog= OBJECT (TDialogView)
fPlotSize: VPoint;
fPlotView: TPlotView;
fSolutionView : TSolutionView;
fPlotDoc : TPlotDoc;
fPlotPICT : PicHandle;
FUNCTION TPlotDialog.DoKeyCommand(
ch: CHAR; aKeyCode: INTEGER;
VAR info: EventInfo): TCommand;
OVERRIDE;
FUNCTION TPlotDialog.DoMenuCommand(
aCmdNumber: CmdNumber):TCommand;
OVERRIDE;
PROCEDURE TPlotDialog.DismissDialog(
dismisser: IDType; flashDismisser: BOOLEAN);
OVERRIDE;
PROCEDURE TPlotDialog.Draw(area: Rect);
OVERRIDE;
PROCEDURE TPlotDialog.EachSubView(
PROCEDURE DoToSubView(
theSubView: TView));
OVERRIDE;
PROCEDURE TPlotDialog.PlotNDrawPICT;
PROCEDURE TPlotDialog.GetPlotValues;
PROCEDURE TPlotDialog.DoSetupMenus; OVERRIDE;
END;
TPStyleCmd = OBJECT (TCommand)
fPlotDialog: TPlotDialog;
fOldPlotSpecs : PlotSpecs;
fNewPlotSpecs : PlotSpecs;
{ Initialize the command; if unsuccessful,
signalled by Failure mechanism }
PROCEDURE TPStyleCmd.IPStyleCmd(
itsPlotDialog:TPlotDialog;
itsNewStyle:PlotSpecsPtr;
itsCmdNumber: CmdNumber);
PROCEDURE TPStyleCmd.DoIt; OVERRIDE;
PROCEDURE TPStyleCmd.RedoIt; OVERRIDE;
PROCEDURE TPStyleCmd.UndoIt; OVERRIDE;
END;
VAR
gDefaultSpecs: PlotSpecs;
{ a Menu Management Global }
gMenuOfs:INTEGER;
{ Convenience, fetching string from resource }
gPromptString: Str255;
IMPLEMENTATION
{ I M P L E M E N T A T I O N }
{--------------------------------}
{$S ARes}
{ Generallly useful routines }
FUNCTION GetPrompt(index: INTEGER): StringPtr;
BEGIN
GetIndString(gPromptString,
kPromptsRsrcID, index);
GetPrompt := @gPromptString;
END;
FUNCTION Real2Str(aReal: Real; theDigits: INTEGER): Str255;
VAR aStr: DecStr;
form : DecForm;
BEGIN
form.style := FixedDecimal;
form.digits := theDigits;
Num2Str(form,aReal,aStr);
Real2Str := aStr;
END;
{$IFC qDebug}
{$IFC qTrace} {$D+} {$ENDC}
{ In the final version of MacApp 2.0 there will some kind of support
for REAL numbers in text entry fields, for now we use Calvins Cocks
code from the Dec 88 Frameworks }
PROCEDURE MyFieldToString(theData: Ptr;
fieldType: integer; VAR theString: str255);
CONST
DecPrec = 2;
{ Change if you want more decimal precision }
TYPE
TAlias = RECORD
CASE integer OF
bReal, bSingle: (asReal : Real);
bDouble: (asDouble : Double);
bExtended: (asExtended : Extended);
END;
VAR
alias : ^TAlias;
aDecForm : DecForm;
x : Extended;
NumStr : DecStr;
BEGIN
alias := Pointer(theData);
WITH alias^ DO
CASE fieldType OF
bReal, bSingle:
BEGIN
aDecForm.style := FixedDecimal;
aDecForm.digits := DecPrec;
x := asReal;
Num2Str(aDecForm, x, NumStr);
theString := str255(NumStr);
END;
bDouble:
BEGIN
aDecForm.style := FixedDecimal;
aDecForm.digits := DecPrec;
x := asDouble;
Num2Str(aDecForm, x, NumStr);
theString := str255(NumStr);
END;
bExtended:
BEGIN
aDecForm.style := FixedDecimal;
aDecForm.digits := DecPrec;
x := asExtended;
Num2Str(aDecForm, x, NumStr);
theString := str255(NumStr);
END;
OTHERWISE StdFieldToString(theData,
fieldType, theString);
END;
END;
{$IFC qTrace} {$D++} {$ENDC}
{$ENDC qDebug}
{--------------------------------}
{$S AReadFile}
PROCEDURE ReadBytes(theRefNum: INTEGER;
size:LONGINT; buffer: Ptr);
{ Utility for reading data from a file }
BEGIN
FailOSErr(FSRead(theRefNum, size, buffer));
END;
{--------------------------------}
{$S AWriteFile}
PROCEDURE WriteBytes(theRefNum: INTEGER;
size: LONGINT; buffer: Ptr);
{ Utility for writing data to a file. }
BEGIN
FailOSErr(FSWrite(theRefNum, size, buffer));
END;
{------------------------------------------}
{$S AInit}
PROCEDURE TPlotApplication.IPlotApplication(
itsMainFileType: OSType);
VAR
fontName:Str255;
aTEView: TTEView;
BEGIN
{ qNeedsHierarchialMenus is a MacApp compile time flag you can set which
will require the use of Heirarchical Menus }
{$IFC NOT qNeedsHierarchialMenus}
IF NOT gConfiguration.hasHierarchicalMenus THEN
BEGIN
gMBarDisplayed := kNonHierDisplayedMBar;
gMenuOfs := 0;
END
ELSE
{$ENDC}
BEGIN
gMBarDisplayed := kHierDisplayedMBar;
gMenuOfs := kHierMenuOffset;
END;
IApplication(itsMainFileType);
{ Do not setup the menus if we were started up with the request to print
}
IF NOT gFinderPrinting THEN
BEGIN
AddResMenu(GetMHandle(mFont), FONT);
SetStyle(cBold, [bold]);
SetStyle(cUnderline, [underline]);
SetStyle(cItalic, [italic]);
SetStyle(cOutline, [outline]);
SetStyle(cShadow, [shadow]);
SetStyle(cCondense, [condense]);
SetStyle(cExtend, [extend]);
END;
{ This is an example of questional code reuse. We know that TTEVIEWS
holds lots of info about fonts, sizes and color and we have the Viewedit
tool at our disposal, so why not use it to create a useful resource to
get our initial values from instead of hard-wiring the defaults. The
technique here is to define a TTEView resource and use all those great
fields that you can setup with viewEdit as the defaults, then steal the
values from the TTEVIEW object and trash the TTEView once all the work
is done. }
{fetch the resource}
aTEView := TTEView(DoCreateViews(NIL, NIL,
kViewRsrcID, gZeroVPt));
FailNIL(aTEView);
{ Set up initial text specs }
GetFontName(aTEView.fTextStyle.tsFont, fontName);
WITH gDefaultSpecs, aTEView DO
BEGIN
theTextFont := fontName;
theTextFace := fTextStyle.tsFace;
theTextSize := fTextStyle.tsSize;
theTextColor := fTextStyle.tsColor;
theJustification := fJustification;
theBackColor := gRGBWhite;
END;
aTEView.Free;
{ Until MacApp 2.0 debug and ViewTemplates support REALs this is our
work around from Calvin Cocks January 89 MapApp Frameworks article.
}
gFieldToStrRtn := @MyFieldToString;
END;
{------------------------------------------}
{$IFC qDebug}
{$S ADebug}
PROCEDURE TPlotApplication.IdentifySoftware;
BEGIN
WriteLn(Plot Source date: 31 Jan 89;Compiled:,
COMPDATE, @ , COMPTIME);
INHERITED IdentifySoftware;
END;
PROCEDURE TPlotApplication.Fields(
PROCEDURE DoToField(fieldName: Str255;
fieldAddr: Ptr;
fieldType:INTEGER));
OVERRIDE;
BEGIN
WITH gDefaultSpecs DO
BEGIN
DoToField( Font, @theTextFont, bFontName);
DoToField( Face, @theTextFace, bStyle);
DoToField( Size, @theTextSize, bInteger);
END;
END;
{$ENDC}
{************************************************}
{ T P l o t D o c u m e n t }
{***** ******************************************}
{------------------------------------------}
{$S AOpen}
PROCEDURE TPlotDoc.IPlotDocument;
VAR
aRect: Rect;
BEGIN
IDocument(kFileType, kSignature,
kUsesDataFork, NOT kUsesRsrcFork,
NOT kDataOpen, NOT kRsrcOpen);
fOldPlot := NIL;
END;
{------------------------------------------}
{$S AOpen}
FUNCTION TPlotApplication.DoMakeDocument(itsCmdNumber: cmdNumber): TDocument;
VAR
aPlotDocument: TPlotDoc;
dimensions: Rect;
BEGIN
{ Allocate and initialize the document}
NEW(aPlotDocument);
FailNIL(aPlotDocument);
aPlotDocument.IPlotDocument;
DoMakeDocument := aPlotDocument;
END;
{----------------------------------------------}
{$S AOpen}
PROCEDURE TPlotDoc.DoInitialState; OVERRIDE;
BEGIN
{ when reverting to an old copy of a document we
need to reset to some reasonable values }
fPlotSpecs := gDefaultSpecs;
fOldPlot := NIL;
END;
{------------------------------------------}
FUNCTION TPlotDoc.DoMakePStyleCmd(itsStyle:PlotSpecsPtr;
itsCmdNumber:CmdNumber): TPStyleCmd ;
VAR
aPStyleCmd:TPStyleCmd;
aPlotDialog: TPlotDialog;
BEGIN
New(aPStyleCmd);
FailNIL(aPStyleCmd);
aPlotDialog := fPlotDialog;
aPStyleCmd.IPStyleCmd(aPlotDialog, itsStyle, itsCmdNumber);
DoMakePStyleCmd := aPStyleCmd;
END;
{------------------------------------------}
{$S AOpen}
PROCEDURE TPlotDoc.DoMakeViews(forPrinting: BOOLEAN);
VAR
aWindow: TWindow;
aPlotDialog: TPlotDialog;
aPlotView: TPlotView;
aTEView: TTEView;
aSolutionView: TSolutionView;
aCluster:TCluster;
aPrintHandler: TStdPrintHandler;
anExtendedText: TExtendedText;
aRect: Rect;
BEGIN
{ We want to dynamically call these in
exisitance. Do a New() call for each object
type, so the linker doesnt strip them out. }
IF gCreateWithTemplates THEN
BEGIN
New(aPlotDialog);
New(aPlotView);
New(aTEView);
New(aSolutionView);
New(aCluster);
New(anExtendedText);
END;
{ we will now ceate and connect up all the view
and document variables }
aWindow := NewTemplateWindow(kPlotDialog, SELF);
{ bring our plot window into exisitance }
aPlotDialog := TPlotDialog(aWindow.FindSubView(DLOG));
FailNIL(aPlotDialog);
{find dialog portions & make certian we have it }
fPlotDialog := aPlotDialog;
{ save this away for late when we need
to easily find the dialog }
aPlotDialog.fPlotDoc := SELF;
{ and of course we need to cross refer so
tell the plotdialog who its doc is }
IF (fOldPlot <> NIL)
| (GetHandleSize(Handle(fOldPlot)) > 0 ) THEN
aPlotDialog.fPlotPICT := fOldPlot
{ If the document has an old plot PICT display it }
ELSE
aPlotDialog.GetPlotValues;
{ Use the values from the resource to
generate the first plot }
{ Find the PlotView and make some
connections to our PlotDocument }
aPlotView := TPlotView(aWindow.FindSubView(plot));
FailNIL(aPlotView);
aPlotView.fPlotDoc := SELF;
aPlotDialog.fPlotView := aPlotView;
aPlotDialog.fPlotPICT := NIL;
aPlotDialog.fPlotSize := aPlotView.fSize;
{ Find the SolutionView and make some
connections to our PlotDocument }
aSolutionView := TSolutionView(aWindow.FindSubView(qslv));
FailNIL(aSolutionView);
aSolutionView.fPlotDoc := SELF;
aPlotDialog.fSolutionView := aSolutionView;
{ while we are at it, retrieve the rectangle
size we will use to display in }
SetRect(aRect,0,0,aSolutionView.fSize.h,
aSolutionView.fSize.v);
aSolutionView.fSolveRect := aRect;
{ we want to limit the minimum size this
window can be so use the size of our
clusters to determine the minimum}
aCluster:=TCluster(aWindow.FindSubView(Ccof));
aWindow.fResizeLimits.top:= aCluster.fSize.v*2;
aWindow.fResizeLimits.left:=aCluster.fSize.h*3;
aCluster:= TCluster(aWindow.FindSubView(Cdsp));
aWindow.fResizeLimits.top := aWindow.fResizeLimits.top
+ aCluster.fSize.v;
NEW(aPrintHandler);
FailNIL(aPrintHandler);
aPrintHandler.IStdPrintHandler(SELF, { its document }
aPlotDialog, { its view }
{ does not have square dots }
FALSE,{ horzontal page size is fixed }
TRUE,{ vertical page size is variable
(could be set to true on
non-style TE systems) }
FALSE);
aPrintHandler.fMinimalMargins := FALSE;
END;
{------------------------------------------}
{$S ASelCommand}
FUNCTION TPlotDoc.DoMenuCommand(
aCmdNumber: CmdNumber): TCommand; OVERRIDE;
VAR
aName: Str255;
menu: INTEGER;
item: INTEGER;
newStyle:PlotSpecs;
{------------------------------------------}
PROCEDURE DoSizeChange(base: CmdNumber);
BEGIN
newStyle.theTextSize := aCmdNumber - base;
DoMenuCommand := DoMakePStyleCmd(
@newStyle, cSizeChange);
END;
{----------------------------------------------}
PROCEDURE DoRelSizeChange(amount: INTEGER);
BEGIN
WITH newStyle DO
theTextSize := theTextSize + amount;
DoMenuCommand := DoMakePStyleCmd(@newStyle, cSizeChange);
END;
{------------------------------------------}
PROCEDURE DoFontChange;
BEGIN
GetItem(GetMHandle(menu), item,newStyle.theTextFont);
GetFNum(aName, newStyle.theFontNum);
DoMenuCommand := DoMakePStyleCmd(@newStyle, cFontChange);
END;
{--------------------------------------------}
PROCEDURE DoColTextChange;
VAR
aColor: RGBColor;
BEGIN
aColor := fPlotSpecs.theTextColor;
IF GetColor(Point($00400040),
GetPrompt(kColTextPrompt)^,
aColor, newStyle.theTextColor) THEN
DoMenuCommand := DoMakePStyleCmd(
@newStyle, cColorText);
END;
{------------------------------------------}
PROCEDURE DoColGraphChange;
VAR
aColor: RGBColor;
BEGIN
aColor := fPlotSpecs.theGraphColor;
IF GetColor(Point($00400040),
GetPrompt(kColGraphPrompt)^, aColor,
newStyle.theGraphColor) THEN
DoMenuCommand := DoMakePStyleCmd(@newStyle, cColorGraph);
END;
{--------------------------------------------}
PROCEDURE DoColAxisChange;
VAR
aColor: RGBColor;
BEGIN
aColor := fPlotSpecs.theAxisColor;
IF GetColor(Point($00400040),
GetPrompt(kColAxisPrompt)^, aColor,
newStyle.theAxisColor) THEN
DoMenuCommand := DoMakePStyleCmd(
@newStyle, cColorAxis);
END;
{----------------------------------------}
PROCEDURE DoColBackChange;
VAR
aColor: RGBColor;
BEGIN
aColor := fPlotSpecs.theBackColor;
IF GetColor(Point($00400040),
GetPrompt(kColBackPrompt)^, aColor,
newStyle.theBackColor) THEN
BEGIN
DoMenuCommand := DoMakePStyleCmd(
@newStyle, cColorBackGround);
END;
END;
{----------------------------------------}
PROCEDURE DoJustChange;
VAR
newJust: INTEGER;
BEGIN
CASE aCmdNumber OF
cJustLeft:
newJust := teJustLeft;
cJustCenter:
newJust := teJustCenter;
cJustRight:
newJust := teJustRight;
END;
newStyle.theJustification := newJust;
DoMenuCommand := DoMakePStyleCmd(@newStyle, aCmdNumber);
END;
{----------------------------------------}
PROCEDURE DoPlainChange;
BEGIN
newStyle.theTextFace := [];
DoMenuCommand := DoMakePStyleCmd(@newStyle, cStyleChange);
END;
{------------------------------------------}
PROCEDURE DoStyleChange;
VAR
newFace : Style;
BEGIN
WITH newStyle DO
BEGIN
CASE aCmdNumber OF
cBold:
newFace := [bold];
cItalic:
newFace := [italic];
cUnderline:
newFace := [underline];
cOutline:
newFace := [outline];
cShadow:
newFace := [shadow];
cCondense:
newFace := [condense];
cExtend:
newFace := [extend];
END;
IF newFace * theTextFace = newFace THEN
theTextFace := theTextFace - newFace
ELSE
theTextFace := theTextFace + newFace;
END;
DoMenuCommand := DoMakePStyleCmd(
@newStyle, cStyleChange);
END;
{----------------------------------------}
BEGIN { DoMenuCommand }
DoMenuCommand := gNoChanges;
newStyle := fPlotSPecs;
CmdToMenuItem(aCmdNumber, menu, item);
IF menu = mFont THEN
DoFontChange
ELSE
CASE aCmdNumber OF
cSizeMin..cSizeMax:
DoSizeChange(cSizeBase);
cSizeGrow:
DoRelSizeChange(kRelSizeAmount);
cSizeShrink:
DoRelSizeChange( - kRelSizeAmount);
cJustLeft..cJustRight:
DoJustChange;
cPlainText:
DoPlainChange;
cBold..cExtend:
DoStyleChange;
cColorText:
DoColTextChange;
cColorGraph:
DoColGraphChange;
cColorAxis:
DoColAxisChange;
cColorBackground:
DoColBackChange;
OTHERWISE
DoMenuCommand := INHERITED
DoMenuCommand(aCmdNumber);
END;
END;
{------------------------------------------}
{$S ARes}
PROCEDURE TPlotDoc.DoSetupMenus; OVERRIDE;
VAR
hasColor:BOOLEAN;
hasStyle:BOOLEAN;
checkPlain: BOOLEAN;
checkSize: BOOLEAN;
checkFont: BOOLEAN;
specChange: BOOLEAN;
just: INTEGER;
item: INTEGER;
fnt: INTEGER;
c:INTEGER;
aMode: INTEGER;
aFace: Style;
aMenuHandle: MenuHandle;
aName: Str255;
aStyle: TextStyle;
theFont: INTEGER;
aStr255: Str255;
BEGIN
INHERITED DoSetupMenus;
hasColor := gConfiguration.hasColorQD;
hasStyle := gConfiguration.hasStyleTextEdit;
aStr255 := fPlotSpecs.theTextFont;
GetFNum(aStr255, aStyle.tsFont);
WITH aStyle, fPlotSpecs DO
BEGIN
tsFace := theTextFace;
tsSize := theTextSize;
tsColor := theTextColor;
END;
checkPlain := aStyle.tsFace = [];
checkFont := TRUE;
aMenuHandle := GetMHandle(mFont);
GetFontName(aStyle.tsFont, aName);
{ Get real font number in case tsFont is }
GetFNum(aName, theFont);
{ the system or application font. }
FOR item := 1 TO CountMItems(aMenuHandle) DO
BEGIN
{ There can be more than 31 menu entries
with scrolling menus, but trying to enable
an item with number > 31 is bad news.
If the menu itself is enabled (which it
will be in MacApp if any of the first 31
items is enabled), then the extras
will always be enabled. }
IF item <= 31 THEN
EnableItem(aMenuHandle, item);
IF checkFont THEN
BEGIN
GetItem(aMenuHandle, item, aName);
GetFNum(aName, fnt);
CheckItem(aMenuHandle, item, fnt = theFont);
END;
END;
just := fPlotSpecs.theJustification;
{ Enable justification related menu items }
EnableCheck(cJustLeft, TRUE, (just = teJustLeft));
EnableCheck(cJustCenter, TRUE, (just = teJustCenter));
EnableCheck(cJustRight, TRUE, (just = teJustRight));
{$IFC NOT qNeedsHierarchialMenus}
IF gConfiguration.hasHierarchicalMenus THEN
{$ENDC}
BEGIN
Enable(cStyle, TRUE); { Enable sub-menus }
Enable(cSize, TRUE);
Enable(cFont, TRUE);
Enable(cColor, hasColor);
END;
aFace := aStyle.tsFace;
EnableCheck(cPlainText, TRUE, checkPlain);
{ Enable normal Style menu items }
EnableCheck(cBold, TRUE, bold IN aFace);
EnableCheck(cItalic, TRUE, italic IN aFace);
EnableCheck(cUnderline, TRUE, underline IN aFace);
EnableCheck(cOutline, TRUE, outline IN aFace);
EnableCheck(cShadow, TRUE, shadow IN aFace);
EnableCheck(cCondense, TRUE,condense IN aFace);
EnableCheck(cExtend, TRUE, extend IN aFace);
FOR c := cSizeMin TO cSizeMax DO
BEGIN
IF hasStyle THEN
checkSize := FALSE
ELSE
checkSize := (c - cSizeBase) = aStyle.tsSize;
EnableCheck(c, TRUE, checkSize);
IF ((NOT hasStyle) |
{ If the record isnt styled, or }
RealFont(aStyle.tsFont,c-cSizeBase))
{ the size is a real one }
THEN aFace := [outline] { then we outline it }
ELSE
aFace := [];
SetStyle(c, aFace);
END;
Enable(cSizeGrow, TRUE);
Enable(cSizeShrink, TRUE);
Enable(cColorText, hasColor);
Enable(cColorBackground, hasColor);
Enable(cColorGraph, hasColor);
Enable(cColorAxis, hasColor);
END;
{------------------------------------------}
{$S AWriteFile}
PROCEDURE TPlotDoc.DoNeedDiskSpace(
VAR dataForkBytes, rsrcForkBytes: LONGINT);
VAR
r:Rect;
BEGIN
{ In other MacApp Samples we would normally get
the Print record space requirements by doing:
INHERITED DoNeedDiskSpace(dataForkBytes, rsrcForkBytes);
BUT seeing as we are trying to imitate a
MacDraw File we will just do our size
calculation
}
dataForkBytes := kHeaderSize { for std MacDraw Header }
+ GetHandleSize(Handle(fPlotDialog.fPlotPICT));
{ For now we will write only the PICT Handle in
the future we might want to write the
PlotSpecs and other parameters to the resource
fork of the file }
rsrcForkBytes := 0;
END;
{------------------------------------------}
{$S AReadFile}
PROCEDURE TPlotDoc.DoRead(aRefNum: INTEGER; rsrcExists, forPrinting:
BOOLEAN);
VAR
fi: FailInfo;
aPICTSize: LONGINT;
aPICTHandle:Handle;
PROCEDURE SkipDocHeaderInfo;
BEGIN
{ skip the dummy header }
FailOSErr( SetFPos(aRefNum,fsFromStart,kHeaderSize)); END;
PROCEDURE HdlReadFailure(error: OSErr; message: LONGINT);
BEGIN
{ We ran into trouble reading the data for
now do nothing}
END;
BEGIN
CatchFailures(fi, HdlReadFailure);
{ Normally, we would ask our ancestors to read
in their data by:
INHERITED DoRead(aRefNum, rsrcExists, forPrinting);
but we are imitating a MacDraw Doc and have
to behave like one
}
SkipDocHeaderInfo;
IF fOldPlot <> NIL THEN
DisposHandle(Handle(fOldPlot));
FailOSErr(GetEOF(aRefNum,aPICTSize));
aPICTSize := aPICTSize - kHeaderSize;
aPICTHandle := NewHandle(aPICTSize);
HLock(aPICTHandle);
ReadBytes(aRefNum, aPICTSize, aPICTHandle^);
HUnLock(aPICTHandle);
fOldPlot := PicHandle(aPICTHandle);
Success(fi);
END;
{------------------------------------------}
{$S AWriteFile}
PROCEDURE TPlotDoc.DoWrite(aRefNum: INTEGER; makingCopy: BOOLEAN);
PROCEDURE WriteHeaderInfo;
VAR
aPtr: Ptr;
BEGIN
aPtr := NewPtrClear(kHeaderSize);
FailNil(aPtr);
WriteBytes(aRefNum, kHeaderSize, aPtr);
DisposPtr(aPtr);
END;
PROCEDURE WritePlotInfo;
VAR
aPICTHandle : Handle;
aPICTSize: LONGINT;
BEGIN
aPICTHandle := Handle(fPlotDialog.fPlotPICT);
aPICTSize := GetHandleSize(aPICTHandle);
HLock(aPICTHandle);
WriteBytes(aRefNum, aPICTSize, aPICTHandle^);
HUnLock(aPICTHandle);
END;
BEGIN
WriteHeaderInfo;
WritePlotInfo
END;
{------------------------------------------}
{$S ARes}
PROCEDURE TPlotDoc.SolveQuadratic;
VAR
a,b,c,check : real;
FUNCTION PositiveCalc(a, b, check:real):real;
BEGIN
PositiveCalc := (-b + sqrt(check)) / (2 * a);
END;
FUNCTION NegativeCalc(a, b, check:real):real;
BEGIN
NegativeCalc := (-b - sqrt(check)) / (2 * a);
END;
BEGIN
a := faParam;
b := fbParam;
c := fcParam;
check := (b * b) - (4 * a * c);
IF check = 0 THEN
{ we have a double root (same place twice) }
BEGIN
fRootType := SingleSolution;
f1stRoot := PositiveCalc(a, b, check);
f2ndRoot := f1stRoot;
END
ELSE IF check > 0 THEN
{ we have a pair of real x axis crossings }
BEGIN
fRootType := RealRoots;
f1stRoot := PositiveCalc(a, b, check);
f2ndRoot := NegativeCalc(a, b, check);
END
ELSE IF check < 0 THEN
{ roots are represented by complex number }
BEGIN
fRootType := ComplexRoot;
check := -check;
f1stRoot := PositiveCalc(a, b, check);
f2ndRoot := NegativeCalc(a, b, check);
END;
END;
{------------------------------------------}
{$S ANonRes}
PROCEDURE TPlotDoc.ChangeBackColor(newColor: RGBColor);
VAR
oldPort: GrafPtr;
itsWindow: TWindow;
BEGIN
itsWindow := TView(fPlotDialog).GetWindow;
IF itsWindow <> NIL THEN
BEGIN
GetPort(oldPort);
SetPort(itsWindow.fWMgrWindow);
RGBBackColor(newColor);
itsWindow.ForceRedraw;
SetPort(oldPort);
END;
END;
{------------------------------------------}
{$IFC qDebug}
{$S AFields}
PROCEDURE TPlotDoc.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr:
Ptr; fieldType: INTEGER)); OVERRIDE;
VAR
aStr : DecStr;
form : DecForm;
aReal: Real;
BEGIN
form.style := FloatDecimal;
form.digits := 6;
DoToField(TPlotDoc, NIL, bClass);
aReal := faParam;
Num2Str(form,aReal,aStr);
DoToField(faParam, @aStr, bString);
aReal := fbParam;
Num2Str(form,aReal,aStr);
DoToField(fbParam, @aStr, bString);
aReal := fcParam;
Num2Str(form,aReal,aStr);
DoToField(fcParam, @aStr, bString);
aReal := fstepParam;
Num2Str(form,aReal,aStr);
DoToField(fstepParam, @aStr, bString);
DoToField(fxParam, @fxParam, bInteger);
DoToField(fyParam, @fyParam, bInteger);
DoToField( Font, @fPlotSpecs.theTextFont, bFontName);
DoToField( Face, @fPlotSpecs.theTextFace, bStyle);
DoToField( Size, @fPlotSpecs.theTextSize, bInteger);
INHERITED Fields(DoToField);
END;
{$ENDC}
{**********************************************}
{ T P l o t D i a l o g }
{**********************************************}
{$S }
PROCEDURE TPlotDialog.DismissDialog(
dismisser: IDType; flashDismisser: BOOLEAN);
OVERRIDE;
BEGIN
INHERITED DismissDialog(dismisser, flashDismisser);
END;
{------------------------------------------}
FUNCTION TPlotDialog.DoKeyCommand(ch: CHAR;
aKeyCode: INTEGER; VAR info: EventInfo): TCommand;
OVERRIDE;
BEGIN
{ If Enter is pressed, assume we have new
parameters and a new plot to create. }
IF (ch = chEnter) THEN
BEGIN
{we have everything we need, lets DOIT!}
PlotNDrawPICT;
{We did all the work no reason to
generate a command}
DoKeyCommand := gNoChanges;END
ELSE
DoKeyCommand := INHERITED
DoKeyCommand(ch, aKeyCode, info);
END;
{------------------------------------------}
FUNCTION TPlotDialog.DoMenuCommand(
aCmdNumber: CmdNumber): TCommand; OVERRIDE;
BEGIN
{ Plot Menu Command was chosen so create plot. }
IF (aCmdNumber = cPlotIt) THEN
BEGIN
PlotNDrawPICT; { we have everything, lets DOIT! }
DoMenuCommand := gNoChanges;
{ We did all the work no reason to generate a command}
END
ELSE
DoMenuCommand := INHERITED DoMenuCommand(aCmdNumber);
END;
{------------------------------------------}
PROCEDURE TPlotDialog.DoSetupMenus; OVERRIDE;
BEGIN
Enable(cPlotIt, TRUE);
INHERITED DoSetupMenus;
END;
{------------------------------------------}
PROCEDURE TPlotDialog.Draw(area: Rect); OVERRIDE;
VAR
plotRect : Rect;
dontCare : BOOLEAN;
BEGIN
dontCare := fPlotView.Focus;
{ set the world up to focus all drawing
in the PlotView }
fPlotView.GetQDFrame(plotRect);
{ the design says we draw into the
available frame }
DrawPicture(fPlotPICT, plotRect);
{ Draw the PICT in the PlotView }
dontCare := SELF.Focus;
{ shift the focus back to us }
END;
{------------------------------------------}
PROCEDURE TPlotDialog.EachSubView(PROCEDURE DoToSubView(theSubView: TView));
BEGIN
{ We do not want all of our clever
dialog elements printing so lets
skip them when printing }
IF NOT gPrinting THEN
INHERITED EachSubView(DoToSubView);
END;
{------------------------------------------}
PROCEDURE TPlotDialog.PlotNDrawPICT;
VAR
plotRect : Rect;
solveRect: Rect;
saveClip : RgnHandle;
pstate : PenState;
dontCare : BOOLEAN;
aFontNum : INTEGER;
BEGIN
GetPlotValues;
{ get current values from the view }
fPlotDoc.SolveQuadratic;
{ for the parameters retrieved, setup
the solution values }
IF fPlotPICT <> NIL THEN
KillPicture(fPlotPICT);
dontCare := fPlotView.Focus;
fPlotView.GetQDExtent(plotRect);
{ change MacApps focus to the plotview
to properly get our plot rect}
dontCare := SELF.Focus;
{ and of course lets set FOCUS back to us.
The above process of setting up plotRect
might have been better handleed by
declaring an fRect in plotview
and having the resize method of plotview
keep it up to date}
fPlotPICT := OpenPicture(plotRect);
saveClip := NewRgn;
FailNIL(SaveClip);
GetClip(SaveClip);
GetPenState(pstate);
{ setup the font info for our plot }
{$Push} {$H-}
GetFNum(fPlotDoc.fPlotSpecs.theTextFont, aFontNum);
{$H+}
TextFont(aFontNum);
TextSize(fPlotDoc.fPlotSpecs.theTextSize);
TextFace(fPlotDoc.fPlotSpecs.theTextFace);
{ we also have: theTextColor,
theJustification, theBackColor
that we might want to do something with
in the future }
TextMode(srcOr);
{Begin MacDraw Document PICT}
PicComment(picDwgBeg, 0, NIL);
PicComment(picGrpBeg, 0, NIL);
fPlotView.AddToPict(plotRect);
solveRect := fSolutionView.fSolveRect;
{ get our plot rect, we know that this
is a fixed rect}
offsetRect(solveRect,4{border},
plotRect.Bottom-(solveRect.Bottom+4{border}));
{ slide the textbox on down to the
bottom of the view area this assumes
that the solution textbox is smaller
than the plotRect}
fSolutionView.AddToPict(solveRect);
PicComment(PicGrpEnd, 0, NIL);
PicComment(picDwgEnd, 0, NIL);
ClosePicture;
SetPenState(pstate);
SetClip(saveClip);
DisposeRgn(saveClip);
ForceRedraw;
{ make the dialog rect invalid }
END;
{------------------------------------------}
PROCEDURE TPlotDialog.GetPlotValues;
BEGIN
fPlotDoc.faParam :=
TExtendedText(FindSubView(cofA)).GetValue;
fPlotDoc.fbParam :=
TExtendedText(FindSubView(cofB)).GetValue;
fPlotDoc.fcParam :=
TExtendedText(FindSubView(cofC)).GetValue;
fPlotDoc.fstepParam :=
TExtendedText(FindSubView(step)).GetValue;
fPlotDoc.fxParam :=
TNumberText(FindSubView(xAxs)).GetValue;
fPlotDoc.fyParam :=
TNumberText(FindSubView(yAxs)).GetValue;
END;
{------------------------------------------}
PROCEDURE TPlotView.GetQDFrame(VAR frameRect:Rect);
VAR
extent: VRect;
BEGIN
GetFrame(extent);
ViewToQDRect(extent, frameRect);
END;
{------------------------------------------}
PROCEDURE TPlotView.AddToPict(picRect:Rect);
CONST
AxisLabelIndent = 4;
TYPE
Widpt = Point;
WidPtr = ^WidPt;
WidHdl = ^WidPtr;
VAR
x, y : Real;
a,b,c : Real;
step : Real;
halfXScale : Real;
xPictScale : Real;
yPictScale : Real;
lastPt : Point;
thisPt : Point;
xScale : INTEGER;
yScale : INTEGER;
CenterHorz : INTEGER;
CenterVert : INTEGER;
PictHorz : INTEGER;
PictVert : INTEGER;
leading: INTEGER;
fInfo : FontInfo;
Width : Widhdl;
axisLabel: str255;
newColor : RGBColor;
oldBack: RGBColor;
oldFore: RGBColor;
drawLine : BOOLEAN;
BEGIN
Width := Widhdl(NewHandle(sizeof(widpt)));
Width^^.h := 10;
Width^^.v := 1;
GetFontInfo(fInfo);
leading := fInfo.descent
+ fInfo.ascent + fInfo.leading;
WITH fPlotDoc DO
BEGIN
{ retrieve the length of our Axis }
xScale := fxParam;
yScale := fyParam;
{ retrieve the coeficients }
a := faParam;
b := fbParam;
c := fcParam;
step := fStepParam;
END;
ClipRect(picRect);
GetForeColor(oldFore);
GetBackColor(oldBack);
PenNormal;
{Draw Graph Boundry}
PicComment(picGrpBeg, 0, NIL);
newColor := fPlotDoc.fPlotSpecs.theBackColor;
RGBBackColor(newColor);
PicComment(SetLineWidth,
GetHandleSize(Handle(Width)), Handle(Width));
FillRect(picRect, white);
FrameRect(picRect);
{Two Axis}
newColor := fPlotDoc.fPlotSpecs.theAxisColor;
RGBForeColor(newColor);
{ find height of our View we will draw into }
PictHorz := picRect.right - picRect.left;
PictVert := picRect.bottom - picRect.top;
{ find the center coordinates of the view }
CenterHorz := PictHorz DIV 2;
CenterVert := PictVert DIV 2;
PicComment(picGrpBeg, 0, NIL);
moveto(0, CenterVert);
line( PictHorz, 0);
moveto(CenterHorz, 0);
line(0, PictVert);
PicComment(picGrpEnd, 0, NIL);
newColor := fPlotDoc.fPlotSpecs.theGraphColor;
RGBForeColor(newColor);
{Axis Text}
{ Place -X axis label to the lowerleft of
the axis line }
moveto(AxisLabelIndent, CenterVert + leading);
NumToString(-xScale,axisLabel);
DrawString(axisLabel);
{ Place +Y axis label to the topleft of the
axis line }
NumToString(yScale,axisLabel);
moveto(CenterHorz - (StringWidth(axisLabel)
+ AxisLabelIndent), leading);
DrawString(axisLabel);
{ Place +X axis label to the lowerright
of the axis line }
NumToString(xScale,axisLabel);
moveto(PictHorz - (StringWidth(axisLabel)
+ AxisLabelIndent), CenterVert + leading);
DrawString(axisLabel);
{ Place -Y axis label to the lowerleft
of the axis line }
NumToString(-yScale,axisLabel);
moveto(CenterHorz - (StringWidth(axisLabel)
+ AxisLabelIndent), PictVert - leading);
DrawString(axisLabel);
{The Plot}
{ calculate a scale factor for the
PICTs axis in the view }
xPictScale := PictHorz / xScale;
yPictScale := PictVert / yScale;
{ calculate our starting x,y point }
halfXScale := xScale / 2;
x := -halfXScale;
y := a * x * x + (b * x) + c;
{ Scale it into the PICTs
(and PostScripts) view space}
thisPt.h :=
integer(round(x * xPictScale))+CenterHorz;
thisPt.v :=
integer(round(-y * yPictScale))+CenterVert;
{ Find where to stop and start drawing.
LOOP until we reach all x values:
1. Find our first visible line segment
2. Plot until it disappears
3. Find a suitable end point
}
WHILE (NOT PtInRect(thisPt,picRect))
& (x <= halfXscale) DO
BEGIN
x := x + step;
y := a * x * x + (b * x) + c;
thisPt.h :=
integer(round(x * xPictScale))+CenterHorz;
thisPt.v :=
integer(round(-y * yPictScale))+CenterVert;
END;
moveTo(thisPt.h,thisPt.v);
drawLine := TRUE;
PicComment(picGrpBeg, 0, NIL);
REPEAT
x := x + step;
y := (a * x * x) + (b * x) + c;
thisPt.h :=
integer(round(x*xPictScale))+CenterHorz;
thisPt.v :=
integer(round(-y*yPictScale))+CenterVert;
IF NOT PtInRect(thisPt,picRect) THEN
drawLine := FALSE
ELSE
BEGIN
IF drawLine THEN
LineTo(thisPt.h,thisPt.v)
ELSE
BEGIN
drawLine := TRUE;
moveTo(thisPt.h,thisPt.v)
END
END;
UNTIL x >= halfXScale;
PicComment(picGrpEnd, 0, NIL);
RGBForeColor(oldFore);
RGBBackColor(oldBack);
PicComment(PicGrpEnd, 0, NIL); {of select all objects}
END;
{------------------------------------------}
PROCEDURE TPlotView.Resize(width,
height: VCoordinate; invalidate: BOOLEAN);
OVERRIDE;
BEGIN
invalidate := TRUE;
INHERITED Resize(width, height, invalidate);
ForceRedraw;
END;
{------------------------------------------}
{ Adds the text box containing the Quadratic equation solution to our
PICT. }
PROCEDURE TSolutionView.AddToPict(picRect: Rect);
CONST
k1stLine = 1; k2ndLine = 2; k3rdLine = 3;
k4thLine = 4; k5thLine = 5;
kLeftJust = 1;
kIndent = 2;
TYPE
Widpt = Point;
WidPtr = ^WidPt;
WidHdl = ^WidPtr;
TTxtPicRec = PACKED RECORD
tJus : Byte;
tFlip : Byte;
tRot : Integer;
tLine : Byte;
tCmnt : Byte;
END;
VAR
TextClipRgn : RgnHandle;
TxtPicRec : TTxtPicRec;
TxtPicPtr : QDPtr;
TxtPicHdl : QDHandle;
Width : WidHdl;
clipBox: Rect;
boxTop : INTEGER;
boxLeft: INTEGER;
leading: INTEGER;
fInfo : FontInfo;
LineNo : INTEGER;
a,b,c : Real;
x1,x2 : Real;
z1,z2 : Real;
newColor : RGBColor;
BEGIN
WITH fPlotDoc DO
BEGIN
{ retrieve the Solution }
x1 := f1stRoot;
x2 := f2ndRoot;
{ retrieve the coeficients }
a := faParam;
b := fbParam;
c := fcParam;
END;
Width := Widhdl(NewHandle(sizeof(widpt)));
Width^^.h := 10;
Width^^.v := 1;
GetFontInfo(fInfo);
leading := fInfo.descent + fInfo.ascent + fInfo.leading;
PicComment(picGrpBeg, 0, NIL);
{Box }
PicComment(picGrpBeg, 0, NIL);
PicComment(SetLineWidth,
GetHandleSize(Handle(Width)),
Handle(Width));
fillRect(picRect, white);
frameRect(picRect);
PicComment(picGrpEnd, 0, NIL); {of box}
TextClipRgn := NewRgn;
FailNil(TextClipRgn);
GetClip(TextClipRgn);
clipBox := picRect;
ClipRect(clipBox);
newColor := fPlotDoc.fPlotSpecs.theTextColor;
RGBForeColor(newColor);
{Box Text}
{ setup our Text Comment Handle }
TxtPicPtr := @TxtPicRec;
TxtPicHdl := @TxtPicPtr;
TxtPicRec.tJus := kLeftJust;
TxtPicRec.tFlip := 0; {no flip}
TxtPicRec.tRot := 0; {no rotation}
TxtPicRec.tLine := 2; {1 1/2 spacing}
{put the Comment into our PICT}
PicComment(TextBegin, sizeof(TTxtPicRec), Handle(TxtPicHdl));
{ Add the BOX text to the PICT }
boxTop := picRect.top;
boxLeft:= picRect.Left;
MoveTo(boxLeft + kIndent,
boxTop + (k1stLine * leading));
DrawString(CONCAT(y=ax^2 + bx + c, chr(13)));
MoveTo(boxLeft + kIndent,
boxTop + (k2ndLine * leading));
DrawString(CONCAT( a=, Real2Str(a,1), , b=, Real2Str(b,1), , c=,
Real2Str(c,1), chr(13)));
{ The solution text is next }
MoveTo(boxLeft + kIndent,
boxTop + (k3rdLine * leading));
DrawString(CONCAT( x1=, Real2Str(x1,3),
, x2=, Real2Str(x2,3), chr(13)));
{ Display kind of Quadratic we have }
MoveTo(boxLeft + kIndent,
boxTop + (k4thLine * leading));
CASE fPlotDoc.fRootType OF
RealRoots :
DrawString(CONCAT(Two Real Roots, x1, x2,
chr(13)));
SingleSolution :
DrawString(CONCAT(Double Root, chr(13)));
ComplexRoot :
DrawString(CONCAT(Two Complex Roots ,chr(13)));
OTHERWISE
;
END;
{ Calculate the slope and add the
string it to the PICT}
WITH fPlotDoc DO
BEGIN
z1 := -b / (2 * a);
z2 := (4 * a * c - (b * b)) / (4 * b);
END;
MoveTo(boxLeft + kIndent,
boxTop + (k5thLine * leading));
DrawString(CONCAT(Slope 0 is (,
Real2Str(z1,1),,, Real2Str(z2,1),),
chr(13)));
{ All done with our text }
PicComment(TextEnd, 0, NIL);
PicComment(PicGrpEnd, 0, NIL); {of Box & text}
DisposHandle(Handle(width));
DisposeRgn(TextClipRgn);
END;
{------------------------------------------}
PROCEDURE TPStyleCmd.DoIt;
BEGIN
fPlotDialog.fPlotDoc.fPlotSpecs := fNewPlotSPecs;
END;
{------------------------------------------}
PROCEDURE TPStyleCmd.ReDoIt;
BEGIN
fPlotDialog.fPlotDoc.fPlotSpecs := fNewPlotSPecs;
END;
{------------------------------------------}
PROCEDURE TPStyleCmd.UnDoIt;
BEGIN
fPlotDialog.fPlotDoc.fPlotSpecs := fOldPlotSPecs;
END;
{------------------------------------------}
PROCEDURE TPStyleCmd.IPStyleCmd(itsPlotDialog: TPlotDialog;
itsNewStyle: PlotSpecsPtr; itsCmdNumber: CmdNumber);
BEGIN
ICommand(itsCmdNumber, itsPlotDialog.fPlotDoc,
itsPlotDialog, NIL);
fPlotDialog := itsPlotDialog;
fOldPlotSPecs:=fPlotDialog.fPlotDoc.fPlotSpecs;
fNewPlotSPecs:=itsNewStyle^;
END;
END.
MPlot.p Main Program FILE
{}
Program Plot;
USES
{ MacApp }
UMacApp,
{ Building Blocks }
UDialog, UPrinting,
{ Implementation Use }
SANE, ToolUtils, Fonts, Resources,
Script, PickerIntf, Packages,
{ the PlotUNIT }
UPlot;
VAR
gPlotApplication: TPlotApplication;
{The application object:}
{----------------------------------------------}
{ T H E M A I N P R O G R A M }
BEGIN
InitUMacApp(8);
{Initialize the Toolbox,
making 8 calls to MoreMasters:}
InitPrinting;
{Initialize the UPrinting unit:}
NEW(gPlotApplication);
{Allocate a new TPlotApplication object:}
FailNIL(gPlotApplication);
gPlotApplication.IPlotApplication(kFileType);
{Initialize that new object:}
gPlotApplication.Run;
{Run the application.
When its done, exit.}
END.
PLOT.r-Plot resource FILE
/* Copyright © 1988-1989 Apple Computer, Inc.
All rights reserved. */
/* Copyright © 1989 Software Architects, Inc.
All rights reserved. */
#if qDebug
include Debug.rsrc;
#endif
include MacApp.rsrc;
include Dialog.rsrc;
include Printing.rsrc;
include Plot CODE;
#define kPlotView1010
#define kViewRsrcID1005
resource seg! (256, purgeable) {
{
GOpen;
GClose;
GNonRes;
GSelCommand
}
};
resource SIZE (-1) {
dontSaveScreen,
acceptSuspendResumeEvents,
enableOptionSwitch,
canBackground,
MultiFinderAware,
backgroundAndForeground,
dontGetFrontClicks,
ignoreChildDiedEvents,
is32BitCompatible,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
#if qDebug
368 * 1024,/* ??? BALLPARK GUESSES ????? */
320 * 1024
#else
(300-32) * 1024,/* ??? BALLPARK GUESSES ?? */
(200-32) * 1024
#endif
};
resource DITL (201, purgeable) {
{
/* [1] */
{160, 182, 180, 262}, Button { enabled, OK };
/* [2] */
{10, 75, 150, 316}, StaticText { disabled,
This is an implementation of the MacTutor Plotter Program.
\n\n written
with MacApp® © 1985-1989 Apple Computer, Inc.};
/* [3] */ {10, 20, 42, 52}, Icon { disabled, 1 }
}
};
resource ALRT (1000, purgeable) {
{44, 48, 130, 358},
1000,
{
OK, visible, sound1,
OK, visible, sound1,
OK, visible, sound1,
OK, visible, sound1
}
};
resource ALRT (201, purgeable) {
{90, 100, 280, 412},
201,
{
OK, visible, silent;
OK, visible, silent;
OK, visible, silent;
OK, visible, silent
}
};
resource cmnu (1) {
1,
textMenuProc,
0x7FFFFFFD,
enabled,
apple,
{
/* [1] */
About Plotter , noIcon, noKey, noMark, plain, cAboutApp;
/* [2] */
-, noIcon, noKey, noMark, plain, nocommand
}
};
resource cmnu (2) {
2,
textMenuProc,
0x7FFFEEFB,
enabled,
File,
{
New, noIcon, N, noMark, plain, cNew;
Open , noIcon, O, noMark, plain,cOpen;
-, noIcon, noKey, noMark, plain, nocommand;
Close, noIcon, noKey, noMark, plain,cClose;
Save, noIcon, S, noMark, plain, cSave;
Save As , noIcon,noKey,noMark,plain, cSaveAs;
Save a Copy In ,
noIcon,noKey,noMark,plain, cSaveCopy;
Revert,noIcon,noKey,noMark,plain, cRevert;
-, noIcon, noKey, noMark, plain,
nocommand;
Page Setup ,
noIcon,noKey,noMark,plain,cPageSetup;
Print ,noIcon,noKey,noMark,plain, cPrint;
-, noIcon, noKey, noMark, plain, nocommand;
Quit,noIcon, Q, noMark, plain, cQuit
}
};
resource cmnu (3) {
3,
textMenuProc,
0x7FFFFFBD,
enabled,
Edit,
{
Undo, noIcon, Z, noMark, plain, cUndo;
-, noIcon, noKey, noMark, plain, nocommand;
Cut, noIcon, X, noMark, plain, cCut;
Copy,noIcon, C, noMark, plain, cCopy;
Paste,
noIcon, V, noMark, plain, cPaste;
Clear,
noIcon, noKey, noMark, plain, cClear;
-, noIcon, noKey, noMark, plain, nocommand;
Show Clipboard,
noIcon, noKey, noMark, plain, cShowClipboard
}
};
/* Hierarchical menu with Style, Size & Font submenus */
resource cmnu (7) {
7,
textMenuProc,
allEnabled,
enabled,
MacAppPlot,
{
Plot,noIcon, noKey, noMark, plain, 1401;
-, noIcon, noKey, noMark, plain,nocommand;
Style, noIcon, \0x1B, \0x08, plain, 2401;
Size,noIcon, \0x1B, \0x09, plain, 2402;
Font,noIcon, \0x1B, \0x0A, plain, 2403;
Color, noIcon, \0x1B, \0x0B, plain, 2404
}
};
/* Hierarchical Style Sub-menu */
resource cmnu (8) {
8,
textMenuProc,
allEnabled,
enabled,
Style,
{
Plain Text, noIcon, P,noMark,plain, 2001;
Bold, noIcon, B,noMark,bold, 2002;
Italic, noIcon,I,noMark,italic,2003;
Underline,noIcon,U, noMark, underline, 2004;
Outline,noIcon,O,noMark,outline, 2005;
Shadow, noIcon,S,noMark,shadow,2006;
Condensed,noIcon,noKey, noMark, condense, 2007;
Extended, noIcon,noKey, noMark, extend, 2008;
-, noIcon, noKey, noMark, plain,nocommand;
Left justified,noIcon, noKey,noMark,plain,2201;
Center justified,noIcon,noKey,noMark,plain,2202;
Right justified,noIcon, noKey,noMark,plain,2203
}
};
/* Hierarchical Size Sub-menu */
resource cmnu (9) {
9,
textMenuProc,
AllEnabled,
enabled,
Size,
{
9 Point, noIcon,noKey, noMark, plain, 2109;
10 Point, noIcon,noKey, noMark, plain, 2110;
12 Point, noIcon,noKey, noMark, plain, 2112;
14 Point, noIcon,noKey, noMark, plain, 1114;
18 Point, noIcon,noKey, noMark, plain, 1118;
24 Point, noIcon,noKey, noMark, plain, 1124;
-, noIcon, noKey, noMark, plain,nocommand;
Grow selection,noIcon, ],noMark,plain, 1198;
Shrink selection,noIcon,[,noMark,plain, 1199
}
};
/* Font menu for hierarchical or non-hierarchical system */
resource MENU (10) {
10,
textMenuProc,
allEnabled,
enabled,
Font,
{ }
};
resource cmnu (11) {
11,
textMenuProc,
allEnabled,
enabled,
Color,
{
Set Graph Color , noIcon, noKey, noMark, plain, 2503;
Set Axis Color , noIcon,noKey, noMark, plain, 2504;
Set Text Color , noIcon,noKey, noMark, plain, 2501;
Set Background Color , noIcon, noKey,noMark, plain, 2502
}
};
resource cmnu (128) {
128,
textMenuProc,
allEnabled,
enabled,
Buzzwords,
{
Style Change,
noIcon,noKey, noMark, plain,cStyleChange;
Size Change,
noIcon,noKey, noMark, plain,2100;
Justification Change,
noIcon,noKey, noMark, plain,2200;
Font Change,
noIcon,noKey, noMark, plain,2300;
Color Change,
noIcon,noKey, noMark, plain,2500;
Page Setup Change,
noIcon,noKey, noMark, plain,
cChangePrinterStyle
}
};
/* Displayed menus on a non-hierarchical system */
resource MBAR (128) {
{1; 2; 3 ; 8; 9; 10; 11}
};
/* Displayed menus on an hierarchical system */
resource MBAR (131) {
{1; 2; 3; 7}
};
/* Hierarchial Sub-Menus */
resource MBAR (130) {
{8; 9; 10; 11}
};
resource STR# (1001, purgeable) {
{
Select a new text color ,
Select background color
Select graph line color
Select axis color
}
};
/* a resource for picking up default text,
graph and color info */
resource view (kViewRsrcID, purgeable) {{
root, TEVW, { 0, 0 }, { 116, 1020 },
sizeVariable, sizePage, shown, enabled,
TEView { TTEView,
withStyle, autoWrap, acceptChanges,
dontFreeText, cTyping, unlimited,
{ 8, 10, 0, 10 },
justLeft, plain, 9, {0, 0, 0}, Geneva }
} };
PLOT.VE.r-Plot View resource FILE
resource view (1010, purgeable) {
{
root, WIND,
{50, 40},
{310, 380}, sizeVariable, sizeVariable,
notShown, enabled,
Window {
TWindow,
zoomDocProc,goAwayBox,resizable,
modeless,ignoreFirstClick,
dontFreeOnClosing,disposeOnFree,
closesDocument,OpenWithDocument,
AdaptToScreen,Stagger,ForceOnScreen,
dontCenter,cofA,
Plot <<<>>>
},
WIND, DLOG,
{0, 0},{240, 294},
sizeSuperView, sizeSuperView, shown, disabled,
DialogView {
TPlotDialog,
noID,
noID
},
DLOG, Ccof,
{2, 5},{90, 96}, sizeFixed, sizeFixed, shown, disabled,
Cluster {
TCluster,
0b0,{1, 1},sizeable,notDimmed,notHilited,
doesntDismiss,{0, 0, 0, 0},
plain,12,{0x0,0x0,0x0},
Helvetica,
Coefficients
},
Ccof, cofA,
{15, 36},{20, 44}, sizeFixed, sizeFixed, shown, enabled,
ExtendedText {
TExtendedText,
0b1101,{1, 1},sizeable,notDimmed,notHilited,
doesntDismiss,{2, 2, 2, 2},
plain,0,{0x0,0x0,0x0},
,
justLeft,1",unlimited,
0b11111000000000000000000100000000,
-10000,10000,2,1.0"
},
Ccof, cofB,
{38, 36}, {20, 44}, sizeFixed, sizeFixed, shown, enabled,
ExtendedText {
TExtendedText,
0b1101,{1, 1},sizeable,notDimmed,notHilited,
doesntDismiss,{2, 2, 2, 2},
plain,0,{0x0,0x0,0x0},
,
justLeft,5",unlimited,
0b11110000000000000000000100000000,
-10000,10000,2,5.0"
},
Ccof, cofC,
{62, 36},
{20, 44}, sizeFixed, sizeFixed, shown, enabled,
ExtendedText {
TExtendedText,
0b1101,{1, 1},sizeable,notDimmed,notHilited,
doesntDismiss,{2, 2, 2, 2},
plain,0,{0x0,0x0,0x0},
,
justLeft,2",unlimited,
0b11110000000000000000000100000000,
-10000,10000,2,2.0"
},
Ccof, VW13,
{15, 10},
{20, 26}, sizeFixed, sizeFixed, shown, disabled,
StaticText {
TStaticText,
0b111,{1, 1},notSizeable,notDimmed,
notHilited,doesntDismiss,{0, 0, 0, 0},
plain,0,{0x0,0x0,0x0},
,
justRight,
a =
},
Ccof, VW14,
{38, 10},
{20, 26}, sizeFixed, sizeFixed, shown, disabled,
StaticText {
TStaticText,
0b111,{1, 1},notSizeable,notDimmed,
notHilited,doesntDismiss,{0, 0, 0, 0},
plain,0,{0x0,0x0,0x0},
,
justRight,
b =
},
Ccof, VW15,
{62, 10},
{20, 26}, sizeFixed, sizeFixed, shown, disabled,
StaticText {
TStaticText,
0b111,{1, 1},notSizeable,notDimmed,
notHilited,doesntDismiss,{0, 0, 0, 0},
plain,0,{0x0,0x0,0x0},
,
justRight,
c =
},
DLOG, Cdsp,
{95, 5},
{139, 96}, sizeFixed, sizeFixed, shown, disabled,
Cluster {
TCluster,
0b0,{1, 1},sizeable,notDimmed,
notHilited, doesntDismiss,{0, 0, 0, 0},
plain,12,{0x0,0x0,0x0},
Helvetica,
Display
},
Cdsp, step,
{26, 36},
{20, 40}, sizeFixed, sizeFixed,shown, enabled,
ExtendedText {
TExtendedText,
0b1111,{1, 1},sizeable,notDimmed,
notHilited,doesntDismiss,{2, 2, 2, 2},
plain,0,{0x0,0x0,0x0},
,
justRight,1",unlimited,
0b11110000000000000000000100000000, 0, 10, 2, 0.25
},
Cdsp, xAxs,
{66, 17},
{20, 60}, sizeFixed, sizeFixed,
shown, enabled,
NumberText {
TNumberText,
0b1111,{1, 1},sizeable,notDimmed,
notHilited, doesntDismiss,{2, 2, 2, 2},
plain,0,{0x0,0x0,0x0},
,
justRight,10",unlimited,
0b11110000000000000000000100000000,10, 1, 1000
},
Cdsp, yAxs,
{106, 17},
{20, 60}, sizeFixed, sizeFixed, shown, enabled,
NumberText {
TNumberText,
0b1111,{1, 1},sizeable,notDimmed,
notHilited,doesntDismiss,{2, 2, 2, 2},
plain,0,{0x0,0x0,0x0},
,
justRight,20",unlimited,
0b11110000000000000000000100000000,20, 1, 1000
},
Cdsp, VW17,
{13, 31},
{12, 40}, sizeFixed, sizeFixed, shown, disabled,
StaticText {
TStaticText,
0b0,{1, 1},notSizeable,notDimmed,
notHilited, doesntDismiss,{0, 0, 0, 0},
plain,9,{0x0,0x0,0x0},
Helvetica,
justCenter,
step
},
Cdsp, VW18,
{54, 17},
{12, 60}, sizeFixed, sizeFixed, shown, disabled,
StaticText {
TStaticText,
0b0,{1, 1},notSizeable,notDimmed,
notHilited,doesntDismiss,{0, 0, 0, 0},
plain,9,{0x0,0x0,0x0},
Helvetica,
justCenter,
X AXIS
},
Cdsp, VW19,
{93, 17},
{12, 60}, sizeFixed, sizeFixed, shown, disabled,
StaticText {
TStaticText,
0b0,{1, 1},notSizeable,notDimmed,
notHilited,doesntDismiss,{0, 0, 0, 0},
plain,9,{0x0,0x0,0x0},
Helvetica,
justCenter,
Y AXIS
},
DLOG, sclr,
{0, 104}, {225, 175},
sizeRelSuperView, sizeRelSuperView, shown, enabled,
Scroller {
TScroller,
VertScrollBar,HorzScrollBar,
0,0,16,16,
noVertConstrain,noHorzConstrain,{0, 0, 0, 0}
},
sclr, plot,
{0, 0}, {400, 400}, sizeSuperView, sizeSuperView,
shown, enabled,
View {TPlotView},
plot, qslv,
{325, 0}, {75, 160},sizeFixed,sizeFixed, shown, enabled,
View {TSolutionView}}
};