Two Editors
Volume Number: | | 7
|
Issue Number: | | 5
|
Column Tag: | | Jörg's Folder
|
Two Simple Editors
By Jörg Langowski, MacTutor Editorial Board
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
Two simple editors
If youve read enough about drawing shapes in windows under MacApp, heres a little break. In fact, the next feature that I wanted to add to the drawing example was to put text boxes into the document. I soon found out that in order to do that in a clean way, one needs to understand the view architecture of MacApp a little better. In order to do that, well diverge from our previous example and look at two small text editor programs.
Views
A view - in the MacApp perspective - is anything that is displayed on a screen. Thus, a window by itself is a view. Anything that is displayed in that window is also a view. Views depend on each other in a hierarchical way; if you display some editable text, some controls and a list in a window, these items will be subviews of the main window view. Each subview can again display other views, which will then depend on that subview, and so on.
In our example, we display editable text in a window. The view class used for displaying a TextEdit record is called TTEView. Our window will contain one subview of this class. MacApp provides a function which creates a window with its associated view hierarchy from a template which is stored in a view resource. In our example (see listing 1&2) NewTemplateWindow (kWindowID, itsDocument) will create a TextEdit window that responds in the usual way to keyboard input, menu commands like Cut, Copy and Paste, and changes the cursor to an I-bar when it is over the TextEdit rectangle in the window. We have set itsDocument to nil because we do not want a document to be associated with the view. Well talk about how to add documents next time.
Well see soon how one creates the view resource, for the moment look at the program example and see with how little code you can program a functioning text editor in MacApp. It wont read or write files yet, neither will it scroll or change the text style (functions that well add later), but it will print its text.
The listing shows that all the important functionality of the window (and therefore of the program) is contained in the constructor routine of the TEditor class, of which our application is an instance (yes, we are finally using constructors in C++/MacApp, instead of the initialization methods that were inherited from Pascal). The applications window is created by NewTemplateWindow, and the TTEView instance is created from its view hierarchy through the MacApp routine FindSubView, which finds a subview by its name.
ViewEdit
So how did we generate the template for our window and the TTEView? MacApp 2.0 provides a wonderful tool, ViewEdit. With this program, you generate a view hierarchy just by drawing it. I cannot go into all the details of that program; the screen image below shows how a typical dialog looks like that is used to change the parameters of a view; in this case, our TTEView.
You see from the dialog which parameters can be controlled through the view template: the upper part of the dialog shows all the attributes of the TTEView, such as fonts, justification, etc., and the lower part controls the superclass (TView) parameters. There, we can name the view template (edit), and determine where it is located in the window and how it responds to resizing of the superview. Through a similar dialog we can control the initialization of the main window. The view resource that we created in this way is added to our program.
Other resources that we may need (size, dialogs, etc.) are contained in the file Defaults.rsrc in the MacApp library. The editor.r Rez file takes some resources from that file, and also defines the File menu. The actual C++ program is only about a page long.
Scrolling the text
The template window created in the first example does not scroll the text. We can add scrolling through several different routes: there exists a TScroller class, which can be a subview of our window and in turn contain the TTEView as a subview. Well talk about that class in a later column; for a very simple scrolling editor, we can create a window that contains one scrollable view using the function NewSimpleWindow (Listing 4). This routine creates a MacApp window from a WIND resource and adds optionally scrollbars. One parameter to the routine is the view that is to be displayed in the window.
Thus, for the second editor example, we create a simple TTEView template with ViewEdit, name it text (why not?) and save it in a view ID=1002 resource which will be copied into our program file. DoCreateViews (Listing 4) will create the view hierarchy corresponding to that resource ID, in our case only one TTEView. Its parameters are the associated document (nil here), the superview (also nil), the view resource ID, and the offset of the view inside its superview (no offset here). gZeroVPt is a (0,0) point in the 32-bit coordinate system that is used by MacApp views.
We then call NewSimpleWindow, with parameters that indicate the window ID, whether or not we want horizontal or vertical scrollbars, the document that is supposed to be displayed in the TTEView (nil, because we are not handling documents in this example), and the view to be displayed.
With these changes, our editor will also scroll the text. It prints already, so all we need to add is file handling. Well do that in the next column.
Forth news
A reader who downloaded Yerk (the public-domain NEON successor which I wrote about some months ago), complained about some bugs that seem to have perpetuated from the original NEON. Walter Kulecz <wkulecz@medics.span.nasa.gov> writes:
Is YERK worth the trouble to learn? Reading the documentation suggested it might be, having source code is a BIG PLUS!, but playing with the command window suggests it might not be.
Problems:
Command window doesnt update if something pops up in front of it. This I can live with. Backspacing the cursor leaves underlines where it was. Again, no real problem but were beginning to look ugly. Zoom to full screen. Note the right hand control border and part of the growbox pollute the new bigger screen. Real Ugly. The real bad news is if your vertical pixel count is not a multiple of your font character height, as once the screen starts scrolling, the characters are clipped and unreadable after scrolling! Presumably this uses the allegedly improved OOPS paradigm in its implementation, so this bug/feature would be inherited by everything else, which of course suggests .... why bother?
Id like to believe. I dont have time to dink around. Answer me back with your opinion of the best example program I should play with to be convinced that YERK is worth while. I may have jumped to a hasty conclusion, but I always give things a second chance.
It is true that the bugs you have discovered make the command window look a little ugly, and they were there in the original NEON from the beginning. However, that should not discourage you from trying out Yerk; the Window class has not much to do with the way the NEON - oops, Yerk - interpreter writes its output into the window. You can define your windows behavior in any way you like. If you have already a big investment into a development in some other language, you are probably not going to rewrite everything in Yerk.
However, as stated here repeatedly, Yerk/NEON is one of the best ways to study and understand object-oriented programming. It was my first exposure to OOP, and has certainly helped me a great deal in understanding other implementations, such as MacApp. For most of you interested in Forth and OOP, Yerk will be a terrific teaching tool, and for some, a tool to create great applications.
See you next month.
Listing 1: editor.h
class TEditor : public TApplication {
public:
pascal TEditor(OSType itsMainFileType);
pascal void HandleFinderRequest();
#ifdef qDebug
virtual pascal void IdentifySoftware();
#endif
};
Listing 2: editor.cp
#include <UMacApp.h>
#include <UPrinting.h>
#include <UTEView.h>
#include <Fonts.h>
#include <ToolUtils.h>
#include editor.h
const OSType kSignature = JLMT;
const OSType kFileType = JL01;
const int kWindowID= 1001;
pascal TEditor::TEditor(OSType itsMainFileType)
{
TTEView*aTEView;
TStdPrintHandler*aStdPrintHandler;
TWindow*aWindow;
IApplication(itsMainFileType);
aWindow = NewTemplateWindow(kWindowID,nil);
FailNIL(aWindow);
aTEView = (TTEView*) aWindow->FindSubView(edit);
FailNIL(aTEView);
aStdPrintHandler = new TStdPrintHandler;
FailNIL(aStdPrintHandler);
aStdPrintHandler->IStdPrintHandler(
nil,
aTEView,
kSquareDots,
kFixedSize,
!kFixedSize);
aWindow->Open();
}
pascal void TEditor::HandleFinderRequest() {};
#ifdef qDebug
pascal void TEditor::IdentifySoftware()
{ProgramReport
(\pEditor ©J.Langowski/MacTutor March 1991,
false);
inherited::IdentifySoftware(); }
#endif
TEditor *gEditor;
int main()
{
InitToolBox();
if (ValidateConfiguration(&gConfiguration))
{
InitUMacApp(8);
InitUPrinting();
InitUTEView();
gEditor = new TEditor(kFileType);
FailNIL(gEditor);
gEditor->Run();
}
else StdAlert(phUnsupportedConfiguration);
return 0;
}
Listing 3: editor.r
/* editor.r
Rez file for MacTutor C++/MacApp Editor example
J. Langowski March 1991 */
#ifndef __TYPES.R__
#include Types.r
#endif
#ifndef __SYSTYPES.R__
#include SysTypes.r
#endif
#ifndef __MacAppTypes__
#include MacAppTypes.r
#endif
#ifndef __ViewTypes__
#include ViewTypes.r
#endif
#if qDebug
include Debug.rsrc;
#endif
include MacApp.rsrc;
include Printing.rsrc;
include Defaults.rsrc SIZE(-1);
include Defaults.rsrc ALRT(phAboutApp);
include Defaults.rsrc DITL(phAboutApp);
include Defaults.rsrc cmnu(mApple);
include Defaults.rsrc cmnu(mEdit);
include Defaults.rsrc cmnu(mBuzzWords);
include Editor CODE;
include editor.rsrc;
#define kSignature JLMT
#define kDocFileType JL01
#define getInfoString©1991 J.Langowski/MacTutor. Translated from MacApp®
Pascal.
resource cmnu (2) {
2,
textMenuProc,
allEnabled,
enabled,
File,
{
Close, noIcon, noKey, noMark, plain, 31;
-, noIcon, noKey, noMark, plain, nocommand;
Page Setup ,
noIcon, noKey, noMark, plain, 176;
Print One, noIcon, P, noMark, plain, 177;
Print , noIcon, noKey, noMark, plain, 178;
-, noIcon, noKey, noMark, plain, nocommand;
Quit, noIcon, Q, noMark, plain, 36
}
};
resource MBAR (kMBarDisplayed,purgeable)
{{mApple; 2; mEdit;} };
resource vers (2,
#if qNames
Package Version,
#endif
purgeable) { 0x02, 0x00, beta, 0x06, verUs, 2.0,
MacApp® 2.0, ©Apple Computer, Inc. 1990
};
resource vers (1,
#if qNames
File Version,
#endif
purgeable) { 0x01, 0x00, beta, 0x05, verUs, Editor,
v 0.8, ©JL/MacTutor 1991
};
resource dbug (kDebugParamsID,
#if qNames
Debug,
#endif
purgeable) {
{350, 4, 474, 636},
/* Bounding rect for debug window */
1, /* Debug window font rsrc ID */
9,/* Debug window font size */
100, /* Number of lines */
100, /* Width of lines in characters */
true, /* open initially */
Jörgs Debug Window /* Window title */
};
Listing 4: editor2.h
class TEditor : public TApplication {
public:
TTEView*fTEView;
TStdPrintHandler*fStdPrintHandler;
TWindow*fWindow;
pascal TEditor(OSType itsMainFileType);
pascal void HandleFinderRequest();
#ifdef qDebug
virtual pascal void IdentifySoftware();
#endif
};
Listing 5: Changed routines for editor2.cp
#include editor2.h
const int kTEViewID= 1002;
pascal TEditor::TEditor(OSType itsMainFileType)
{
IApplication(itsMainFileType);
fTEView = (TTEView*)
DoCreateViews(nil,nil,kTEViewID,&gZeroVPt);
FailNIL(fTEView);
fWindow = NewSimpleWindow(kDefaultWindowID,
kWantHScrollBar,kWantVScrollBar, nil, fTEView);
FailNIL(fWindow);
fStdPrintHandler = new TStdPrintHandler;
FailNIL(fStdPrintHandler);
fStdPrintHandler->IStdPrintHandler( nil, fTEView,
kSquareDots,kFixedSize,!kFixedSize);
fWindow->SetTitleForDoc
(\pMacTutor Editor Window);
fWindow->Open();
}
Listing 6: Changes from editor.r to editor2.r
include Defaults.rsrc WIND(kDefaultWindowID);
include Editor2 CODE;
include editor2.rsrc;