This is GUI.m in view mode; [Download] [Up]
#import "GUI.h"
#import "GUI_view.h"
#import <appkit/appkit.h>
#import <tcl.h>
// GUI.m
// Copyright 1995 by Florian Marquardt (a0047@freenet.uni-bayreuth.de)
// You may freely copy, distribute and reuse this code
// No warranties, of course.
// For the tcl7.3 - license, start PencilTWO and select "Copyright" in the Help Panel.
// When you implement tcl interfaces to other classes or other interesting additions,
// please mail me the code, so I can add it to the next release of Pencil!
// This file contains all Pencil-independent TCL commands that deal
// with the interface to (some of) NEXTSTEPs GUI objects
// Object id's are stored as ClientData in tcl-command -structures.
// The tcl commands will be given names like ".b4" (b for button), ".v8" etc.
// see GUI_newobject(), GUI_findobject(), GUI_deleteobject()
// the command names are kept in a list (search for COMMANDLIST)
// the "new" command creates new objects (e. g. "new window ...")
// commands are of the form:
// int
// GUI_commandname(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
// {
// if(argc>= necessary # of arguments, including cmd) {
// if([CD isKindOf:[Necessary class]]) {
// ... do something ...
// return TCL_OK;
// }
// }
// ERR("Use: <class> cmd <arg1> <arg2> ...");
// }
// You should be able to compile this file independent of Pencil, e.g. into a bundle:
// load the bundle and call [[myBundle principalClass] initTCLCommands:(Tcl_Interp *)myTCLinterp: (id)self] (i.e. you must have created "myTCLinterp" before - with Tcl_CreateInterpreter())
Tcl_HashTable GUI_cmds; // cmd names
Tcl_HashTable GUI_new_cmds; // cmds for 'new' method
Tcl_HashTable GUI_actionTable; // table of tcl progs that are invoked when a button is pressed etc.
Tcl_HashTable GUI_idToName; // table id --> name as tcl cmd (for views)
struct GUI_cmd { char *name; int (*func)(); };
struct GUI_cmdo { char *name; Tcl_CmdProc *func; };
typedef int (myproc) _ANSI_ARGS_((Tcl_Interp *interp, int argc, char *argv[]));
#define ERR(a) { Tcl_SetResult(interp, a, TCL_STATIC); return TCL_ERROR; }
#define EQ(a,b) if(!strcmp(a,b))
#define SETRES(a) strcpy(interp->result, a)
#define ISKINDOF(a,b) if([(id)(a) isKindOf:(b)])
#define CD ((id)cd)
char GUI_string[200]; // general purpose string
NXRect *GUI_therect; // pointer to rectangle passed to drawSelf
NXEvent GUI_lastmousedown; // needed for dragging
// "general" Cmd, called when any object is invoked as a command
// looks at first argument to determine method to be called
int
GUI_generalCmd(ClientData cd, Tcl_Interp *interp, int argc, char * argv[])
{
Tcl_HashEntry *entry;
if(argc>=2)
{
if(entry=Tcl_FindHashEntry( &GUI_cmds, argv[1] ))
{
return ( (Tcl_CmdProc *) (Tcl_GetHashValue(entry))) ( cd, interp, argc, argv );
}
}
ERR("GUI object: unknown method");
}
// create Hash Table for looking up "new"-cmds
void
GUI_createTable( Tcl_HashTable *tbl, struct GUI_cmd *list)
{
int pos;
Tcl_InitHashTable(tbl, TCL_STRING_KEYS);
while(list->name) {
Tcl_SetHashValue( Tcl_CreateHashEntry( tbl, list->name, &pos),
list->func );
++list;
}
}
// same for methods (cmds acting on object)
void
GUI_createGenTable( Tcl_HashTable *tbl, struct GUI_cmdo *list)
{
int pos;
Tcl_InitHashTable(tbl, TCL_STRING_KEYS);
while(list->name) {
Tcl_SetHashValue( Tcl_CreateHashEntry( tbl, list->name, &pos),
list->func );
++list;
}
}
// add prefix to command name if tcl variable _CmdPrefix is set
char GUI_cmdname[50];
char *GUI_cmd_name(Tcl_Interp *interp, char *name)
{
char *s;
s=Tcl_GetVar(interp, "_CmdPrefix", 0);
if(s) {
strcpy(GUI_cmdname, s);
strcat(GUI_cmdname, name);
return(GUI_cmdname);
} else {
return(name);
}
}
// create a new tcl command (name is of form ".t23", ".B12" etc.) which has
// the given id attached to it as ClientData
char *GUI_newobject(Tcl_Interp *ip, char l, id theid)
{
static int num=0;
static char key[20];
sprintf(key, ".%c%d", l, num++);
Tcl_CreateCommand( ip, key, (Tcl_CmdProc *)GUI_generalCmd, (ClientData) theid, NULL);
return(key);
}
// find object-id for given key (command-name, e. g. ".w4")
id GUI_findobject( Tcl_Interp *ip, char *key)
{
static Tcl_CmdInfo info;
if(Tcl_GetCommandInfo(ip, key, &info)) {
return (id)info.clientData;
} else
return nil;
}
void GUI_removeAction(id what)
{
Tcl_HashEntry *entry;
if(entry=Tcl_FindHashEntry( &GUI_actionTable, (char *)what)) {
free((char *)Tcl_GetHashValue(entry));
Tcl_DeleteHashEntry( entry);
}
}
// remove tcl command for an object
void GUI_deleteobject( Tcl_Interp *ip, char *name)
{
if(name[0]!=0 && (name[1]=='w' || name[1]=='v')) { // a window / view, remove everything inside...
Tcl_VarEval( ip, "_close ", name, NULL);
}
GUI_removeAction(GUI_findobject( ip, name));
Tcl_DeleteCommand( ip, name);
}
// add tcl-id (".b7") to list of objects contained in a window (".c.w2")
void GUI_addToView(Tcl_Interp *ip, char *what, id what_id, char *to)
{
id view;
if(!to) to=Tcl_GetVar( ip, ".curwin", TCL_GLOBAL_ONLY);
if(view=GUI_findobject( ip, to)) {
sprintf(GUI_string, ".c%s", to);
Tcl_SetVar2( ip, GUI_string, what, "", TCL_GLOBAL_ONLY);
if([view isKindOf:[Window class]]) {
[[view contentView] addSubview:what_id];
} else
if([view isKindOf: [View class]]) {
[view addSubview: what_id];
}
}
}
// add new action to action table, key is id of object that sends the action
void GUI_insertAction(id forid, char *what)
{
Tcl_HashEntry *entry;
char *whatnew;
int pos;
entry=Tcl_CreateHashEntry(&GUI_actionTable, (char *)forid, &pos);
if(entry) {
whatnew=(char *)malloc(sizeof(char)*(strlen(what)+1));
strcpy(whatnew, what);
Tcl_SetHashValue( entry, whatnew);
}
}
char *GUI_findAction(id sender)
{
Tcl_HashEntry *entry;
if(entry=Tcl_FindHashEntry( &GUI_actionTable, (char *)sender)) {
return (char *)Tcl_GetHashValue(entry);
} else
return NULL;
}
// general "new" cmd:
int
GUI_newCmd(ClientData cd, Tcl_Interp *interp, int argc, char * argv[])
{
Tcl_HashEntry *entry;
if(argc>=2)
{
if(entry=Tcl_FindHashEntry( &GUI_new_cmds, argv[1] ))
{
return ( (myproc *) (Tcl_GetHashValue(entry))) ( interp, argc, argv );
}
}
ERR("Usage: new window| button| textfield| image| view| scrollview| slider| browser");
}
// methods:
int
GUI_free(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
GUI_deleteobject(interp, argv[0]);
ISKINDOF(cd, [Window class]) { [CD free]; } else {
if([CD isMemberOf:[View class]]) [CD removeFromSuperview];
[CD free]; }
return TCL_OK;
}
int
GUI_remove(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
GUI_deleteobject(interp, argv[0]);
return TCL_OK;
}
int
GUI_select(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
id sel;
if(argc>=3 && ([CD isKindOf: [NXBrowser class]] || [CD isKindOf: [Matrix class]])) {
if([CD isKindOf: [NXBrowser class]]) sel=[CD matrixInColumn:0]; else sel=CD;
[sel selectCellAt: atoi(argv[2]): 0];
return TCL_OK;
}
ERR("? <browser> select <#>");
}
int
GUI_setValue(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf:[Control class]]) {
if([CD isMemberOf:[Button class]]) {
int thestate;
Tcl_ExprBoolean( interp, argv[2], &thestate);
[CD setIntValue: thestate];
}
else
if([CD isKindOf: [NXBrowser class]] || [CD isKindOf: [Matrix class]]) {
id sel;
int rows, cols;
int i;
int flag;
int count;
char **argvp;
Tcl_SplitList( interp, argv[2], &count, &argvp);
Tcl_SetResult(interp, "", TCL_VOLATILE);
if([CD isKindOf: [NXBrowser class]]) sel=[CD matrixInColumn:0]; else sel=CD;
[sel getNumRows: &rows numCols:&cols];
if(rows>count) rows=count;
[[CD window] disableDisplay];
[sel selectCellAt:-1:-1];
for(i=0;i<rows;i++) {
Tcl_ExprBoolean( interp, argvp[i], &flag);
if(flag) { [[[sel cellAt:i:0] setParameter:NX_CELLHIGHLIGHTED to:1] setState:1]; }
}
free(argvp);
[[CD window] reenableDisplay];
[CD display];
return TCL_OK;
} else
[CD setStringValue: argv[2]];
return TCL_OK;
}
}
ERR("Use: <> setValue <string>");
}
int
GUI_setMultipleSelection(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf: [NXBrowser class]]) {
int flag;
Tcl_ExprBoolean( interp, argv[2], &flag);
[CD setMultipleSelectionEnabled: flag];
return TCL_OK;
}
}
ERR("Use: <browser> setMultipleSelection <flag>");
}
int
GUI_setEmptySelection(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf: [NXBrowser class]]) {
int flag;
Tcl_ExprBoolean( interp, argv[2], &flag);
[CD setEmptySelectionEnabled: flag];
return TCL_OK;
}
}
ERR("Use: <browser> setEmptySelection <flag>");
}
int
GUI_startDragging(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
const char *const mytypes[1]= { NXAsciiPboardType };
id img;
if(argc>=6) {
if([CD isKindOf: [GUI_view class]] && (img=GUI_findobject( interp, argv[3]))) {
Pasteboard *pboard = [Pasteboard newName:NXDragPboard];
NXPoint mypos, none={ 0,0 };
mypos.x=atof(argv[4]); mypos.y=atof(argv[5]);
/* Declare the type of data and place it on the pasteboard. */
[pboard declareTypes: mytypes num:1 owner: NULL];
[pboard writeType: NXAsciiPboardType data: argv[2] length: strlen(argv[2])+1];
/* Now invoke dragImage:.*/
[CD dragImage: img at: &mypos offset: &none event: &GUI_lastmousedown
pasteboard:pboard source: CD slideBack: YES];
// Finished!
return TCL_OK;
}
}
ERR("Use: <view> startDragging <contents> <image> <x> <y>");
}
int
GUI_setDragProc(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf: [GUI_view class]]) {
if(strcmp(argv[2], "")) {
[CD setDragging: 1];
sprintf( GUI_string, "%s.dr", argv[0]);
Tcl_SetVar( interp, GUI_string, argv[2], TCL_GLOBAL_ONLY);
} else [CD setDragging: 0];
return TCL_OK;
}
ERR("Use: <view> setDragProc <proc>");
}
int
GUI_setDragSource(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf: [GUI_view class]]) { [CD setDragSource: atoi(argv[2])];
return TCL_OK; }
ERR("?: <view> setDragSource <flag>");
}
int
GUI_hideDisplay(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf: [Window class]]) {
[CD disableDisplay];
Tcl_Eval( interp, argv[2]);
[CD reenableDisplay];
return TCL_OK;
}
ERR("? <win> hideDisplay <cmds>");
}
int
GUI_setHorizScrolling(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf: [ScrollView class]]) {
int flag;
Tcl_ExprBoolean( interp, argv[2], &flag);
[CD setHorizScrollerRequired: flag];
return TCL_OK;
}
}
ERR("Use: <scrollview> setHorizScrolling <flag>");
}
int
GUI_setVertScrolling(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf: [ScrollView class]]) {
int flag;
Tcl_ExprBoolean( interp, argv[2], &flag);
[CD setVertScrollerRequired: flag];
return TCL_OK;
}
}
ERR("Use: <scrollview> setVertScrolling <flag>");
}
int
GUI_orderFront(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [Window class]]) {
[CD makeKeyAndOrderFront: nil];
return TCL_OK;
}
ERR("orderFront: window?");
}
int
GUI_close(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [Window class]]) {
[CD orderOut: nil];
return TCL_OK;
}
ERR("? <win> close");
}
int
GUI_composite(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=5 && [CD isKindOf: [NXImage class]]) {
NXPoint pt;
pt.x=atof(argv[2]); pt.y=atof(argv[3]);
if(argv[4][0]=='s') {
[CD composite: NX_SOVER toPoint: &pt];
} else {
if(argv[4][0]=='c') {
[CD composite: NX_COPY toPoint: &pt];
} else {
[[CD bestRepresentation] drawAt: &pt];
}
}
return TCL_OK;
}
ERR("Use: <img> composite <x> <y> copy|sover|draw");
}
int
GUI_saveAs(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf: [NXImage class]]) {
NXStream *s;
if(s=NXOpenMemory( NULL, 0, NX_WRITEONLY)) {
[CD writeTIFF: s];
NXSaveToFile( s, argv[2]);
NXClose(s);
return TCL_OK;
}
}
ERR("? <img> saveAs <file.tiff>");
}
int
GUI_setSize(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=4 && [CD isKindOf: [NXImage class]]) {
NXSize s;
s.width=atof(argv[2]);
s.height=atof(argv[3]);
[CD setScalable: YES];
[CD setSize: &s];
return TCL_OK;
}
ERR("? <img> setSize <w> <h>");
}
int
GUI_size(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [NXImage class]]) {
NXSize s;
[CD getSize: &s];
sprintf(interp->result, "%g %g", s.width, s.height);
return TCL_OK;
}
ERR("? <img> size");
}
int
GUI_textLength(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [Text class]]) {
sprintf( interp->result, "%d", [CD textLength]);
return TCL_OK;
}
ERR("textLength: text!");
}
int
GUI_sel(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [Text class]]) {
NXSelPt start, end;
[CD getSel: &start: &end];
sprintf( interp->result, "%d %d", (int)start.cp, (int)end.cp);
return TCL_OK;
}
ERR("sel: text!");
}
int
GUI_setSel(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=4 && [CD isKindOf: [Text class]]) {
[CD setSel: atoi(argv[2]): atoi(argv[3])];
return TCL_OK;
}
ERR("Use: <txt> setSel <start> <end>");
}
int
GUI_getString(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=4 && [CD isKindOf: [Text class]]) {
int length=atoi(argv[3]);
Tcl_SetResult( interp, (char *)malloc(sizeof(char)*(length+1)), TCL_DYNAMIC);
[CD getSubstring: interp->result start: atoi(argv[2]) length: length];
interp->result[length]=0;
return TCL_OK;
}
ERR("Use: <txt> getString <start> <length>");
}
int
GUI_line2pos(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf: [Text class]]) {
sprintf(interp->result, "%d", [CD positionFromLine:atoi(argv[2])]);
return TCL_OK;
}
ERR("<txt> line2pos <line#>");
}
int
GUI_pos2line(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf: [Text class]]) {
sprintf(interp->result, "%d", [CD lineFromPosition:atoi(argv[2])]);
return TCL_OK;
}
ERR("<txt> pos2line <pos#>");
}
int
GUI_setImage(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf:[Button class]]) {
if(argc>=3) {
id what;
if((what=GUI_findobject( interp, argv[2])) && [what isKindOf:[NXImage class]]) {
[CD setImage: what];
if(argc>=4 && !strcmp( argv[3], "-above"))
[CD setIconPosition: NX_ICONABOVE];
else
[CD setIconPosition: NX_ICONONLY];
return TCL_OK;
} else
ERR("setImage: no such image");
} else {
ERR("Usage: <button> setImage <image> (-above)");
} } else
ERR("setImage: <button>!");
}
int
GUI_value(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
ISKINDOF(cd, [Control class]) {
if([CD isMemberOf: [Button class]]) Tcl_SetResult(interp, [CD intValue] ? "1":"0", TCL_STATIC);
else
if([CD isKindOf: [NXBrowser class]] || [CD isKindOf: [Matrix class]]) {
id sel;
int rows, cols;
int i;
Tcl_SetResult(interp, "", TCL_VOLATILE);
if([CD isKindOf: [NXBrowser class]]) sel=[CD matrixInColumn:0]; else sel=CD;
[sel getNumRows: &rows numCols:&cols];
for(i=0;i<rows;i++) {
if([[sel cellAt:i:0] state])
Tcl_AppendElement( interp, "1");
else
Tcl_AppendElement( interp, "0");
}
return TCL_OK;
}
else
Tcl_SetResult(interp, (char *)[CD stringValue], TCL_VOLATILE); return TCL_OK;
}
ERR("value: browser|textfield|slider|button?");
}
int
GUI_refresh(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [NXBrowser class]]) {
[CD loadColumnZero];
return TCL_OK;
}
ERR("Use: <browser> refresh");
}
int
GUI_setTitle(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf: [NXBrowser class]])
{
[CD setTitle: argv[2] ofColumn:0];
return TCL_OK;
}
else
if([CD isKindOf: [Window class]] || [CD isKindOf: [Button class]]) {
[CD setTitle: argv[2]];
return TCL_OK;
}
}
ERR("Use: <> setTitle <title>");
}
int
GUI_display(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if([CD isKindOf: [View class]] || [CD isKindOf: [Window class]]) {
[CD display];
return TCL_OK;
}
ERR("display: view/window?");
}
int
GUI_addText(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3 && [CD isKindOf:[Text class]]) {
int txtlength=[CD textLength];
if(argc<4)
[CD setSel:txtlength:txtlength];
[CD replaceSel:argv[2]];
if(argc<4)
[CD scrollSelToVisible];
return TCL_OK;
}
ERR("Use: <txt> addText <text>");
}
int
GUI_setFont(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=4 && [CD isKindOf:[Text class]]) {
int txtlength=[CD textLength];
if(argc<5)
[CD setSel:txtlength:txtlength+1];
[CD setSelFont: [Font newFont: argv[2] size: atof(argv[3])]];
return TCL_OK;
}
ERR("Use: <txt> setFont <fontname> <size>");
}
int
GUI_drawPS(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=2) {
DPSPrintf(DPSGetCurrentContext(), "\n%s\n", argv[1]);
return TCL_OK;
}
ERR("Use: drawPS <PS-code>");
}
int
GUI_lockFocus(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf:[View class]]) {
[CD lockFocus];
Tcl_Eval(interp, argv[2]);
[CD unlockFocus];
[[CD window] flushWindow];
return TCL_OK;
} else
if([CD isKindOf: [NXImage class]]) {
[CD lockFocus];
Tcl_Eval(interp, argv[2]);
[CD unlockFocus];
return TCL_OK;
}
}
ERR("Use: <view> lockFocus <drawing proc>");
}
int
GUI_setDrawSelf(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
sprintf(GUI_string, "%s.ds", argv[0]);
Tcl_SetVar( interp, GUI_string, argv[2], TCL_GLOBAL_ONLY);
return TCL_OK;
}
ERR("Use: <view> setDrawSelf <drawing proc>");
}
int
GUI_setAction(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
if([CD isKindOf:[Control class]] || [CD isKindOf: [Window class]]) {
GUI_removeAction(CD);
GUI_insertAction(CD, argv[2]);
if([CD isKindOf: [Window class]]) {
[CD setDelegate: GUI_findobject(interp, ".G0")];
} else {
[[CD setAction: @selector(doSomething:)] setTarget: GUI_findobject(interp, ".G0")];
}
return TCL_OK;
}
}
ERR("Use: <control> setAction <action proc>");
}
int
GUI_setMouseDown(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
sprintf(GUI_string, "%s.ms", argv[0]);
Tcl_SetVar( interp, GUI_string, argv[2], TCL_GLOBAL_ONLY);
return TCL_OK;
}
ERR("Use: <view> setMouseDown <cmds>");
}
int
GUI_visibleRect(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
sprintf(interp->result, "%g %g %g %g", GUI_therect->origin.x, GUI_therect->origin.y, GUI_therect->size.width, GUI_therect->size.height);
return TCL_OK;
}
#define SETVALUE(a,b) sprintf(GUI_string, "%g", b); Tcl_SetVar(interp, a, GUI_string, 0)
int
GUI_mouseDragging(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
if(argc>=3) {
int oldMask;
NXEvent thisEvent;
NXEvent *te;
BOOL queue=0, shouldLoop=YES;
oldMask = [[CD window] addToEventMask:NX_LMOUSEDRAGGEDMASK];
if(Tcl_GetVar(interp, "_queueMouse", TCL_GLOBAL_ONLY)) queue=1;
Tcl_SetVar(interp, "_mup", "0", 0);
while (shouldLoop) {
if(queue) {
do {
te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
NX_LMOUSEDRAGGEDMASK)];
} while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));
} else
{
te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
NX_LMOUSEDRAGGEDMASK)];
}
if(te->type==NX_LMOUSEUP) { Tcl_SetVar(interp, "_mup", "1", 0); shouldLoop=NO; }
[CD convertPoint:&te->location fromView:nil];
SETVALUE("_mx", te->location.x);
SETVALUE("_my", te->location.y);
Tcl_Eval(interp, argv[2]);
if(queue) NXPing();
}
[[CD window] setEventMask:oldMask];
return TCL_OK;
} else
ERR("Use: <view> mouseDragging <cmds>");
}
int
GUI_autosize(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
unsigned int mask=0;
if([CD isKindOf: [View class]]) {
while(argc-->=1) {
if(argv[argc][0]=='n') mask|=NX_NOTSIZABLE;
if(argv[argc][0]=='l') mask|=NX_MINXMARGINSIZABLE;
if(argv[argc][0]=='w') mask|=NX_WIDTHSIZABLE;
if(argv[argc][0]=='r') mask|=NX_MAXXMARGINSIZABLE;
if(argv[argc][0]=='t') mask|=NX_MINYMARGINSIZABLE;
if(argv[argc][0]=='h') mask|=NX_HEIGHTSIZABLE;
if(argv[argc][0]=='b') mask|=NX_MAXYMARGINSIZABLE;
}
[CD setAutosizing: mask];
[[CD superview] setAutoresizeSubviews: YES];
return TCL_OK;
}
ERR("autosize: view?");
}
int
GUI_alertPanel(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
{
int r;
if(argc>=4) {
if(argc>=6)
r=NXRunAlertPanel(argv[1], argv[2], argv[3],argv[4],argv[5]);
else
if(argc>=5)
r=NXRunAlertPanel(argv[1], argv[2], argv[3],argv[4], NULL);
else
r=NXRunAlertPanel(argv[1], argv[2], argv[3], NULL, NULL);
sprintf(interp->result, "%d", r);
return TCL_OK;
}
ERR("? alertPanel <title> <txt> <b1> (<b2> <b3>)");
}
// "new"-cmds:
// open window
int
GUI_wopen( Tcl_Interp *interp, int argc, char *argv[])
{
NXRect mycontent;
int style=0, bmask=0, backing=0, defer=NO, hide=NO;
id mywindow;
if(argc>=7)
{
mycontent.origin.x=atof(argv[2]);
mycontent.origin.y=atof(argv[3]);
mycontent.size.width=atof(argv[4]);
mycontent.size.height=atof(argv[5]);
if(argc>=8) {
while(--argc>6) {
#define EQA(c) EQ(argv[argc], c)
EQA("titled") style|=NX_TITLEDSTYLE;
EQA("plain") style|=NX_PLAINSTYLE;
EQA("resize") style|=NX_RESIZEBARSTYLE;
EQA("close") bmask|=NX_CLOSEBUTTONMASK;
EQA("buffered") backing|=NX_BUFFERED;
EQA("miniaturize") bmask|=NX_MINIATURIZEBUTTONMASK;
EQA("retained") backing|=NX_RETAINED;
EQA("nonretained") backing|=NX_NONRETAINED;
EQA("defer") defer=YES;
EQA("hide") hide=YES;
}
} else {
style=NX_RESIZEBARSTYLE;
backing=NX_BUFFERED;
bmask=NX_CLOSEBUTTONMASK | NX_MINIATURIZEBUTTONMASK;
}
if(mywindow=[[Window alloc] initContent: &mycontent
style: style
backing: backing
buttonMask: bmask
defer: defer]) {
SETRES(GUI_newobject(interp, 'w', mywindow));
[mywindow setTitle: argv[6]];
[mywindow display];
[mywindow setFreeWhenClosed: NO];
Tcl_SetVar( interp, ".curwin", interp->result, TCL_GLOBAL_ONLY);
if(!hide) [mywindow makeKeyAndOrderFront:nil];
return TCL_OK;
}
ERR("window open: Couldn't");
}
else
{
ERR("Usage: new window <x> <y> <width> <height> <title> titled| plain| resize| miniaturize| close| buffered| retained| nonretained| defer| hide(...)");
}
}
#define LOOKFORWINDOW(pos, whname, wh) if(argc>=(pos+2)) { if(!strcmp(argv[pos], "-window")) GUI_addToView( interp, whname, wh, argv[pos+1]); } else GUI_addToView( interp, whname, wh, NULL);
// new button
int
GUI_bnew(Tcl_Interp *interp, int argc, char *argv[])
{
id button;
NXRect mf;
if(argc>= 8)
{
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
if(button=[[Button alloc] initFrame:&mf title:argv[6] tag:0 target:GUI_findobject(interp, ".G0") action:@selector(doSomething:) key:0 enabled: YES]) {
SETRES(GUI_newobject(interp, 'b', button));
if(argc>=9 && !strcmp(argv[8],"-switch")) {
[button setType:NX_SWITCH];
LOOKFORWINDOW(9, interp->result, button)
} else {
LOOKFORWINDOW(8, interp->result, button)
}
GUI_insertAction( button, argv[7]);
return TCL_OK;
}
}
ERR("Usage: new button <x> <y> <w> <h> <title> <action> (-switch) (-window <win>)");
}
// new textfield
int
GUI_tnew(Tcl_Interp *interp, int argc, char *argv[])
{
id text;
NXRect mf;
if(argc>= 7)
{
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
if(text=[[[[TextField alloc] initFrame:&mf] setAction: @selector(doSomething:)] setTarget: GUI_findobject(interp, ".G0")]) {
SETRES(GUI_newobject(interp, 't', text));
LOOKFORWINDOW(7, interp->result, text)
GUI_insertAction( text, argv[6]);
return TCL_OK;
}
}
ERR("Usage: new textfield <x> <y> <w> <h> <action> (-window <win>)");
}
int
GUI_newtext(Tcl_Interp *interp, int argc, char *argv[])
{
id text;
NXRect mf;
if(argc>= 6)
{
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
if(text=[[Text alloc] initFrame:&mf text:"" alignment: NX_LEFTALIGNED]) {
SETRES(GUI_newobject(interp, 'T', text));
LOOKFORWINDOW(6, interp->result, text)
[text setVertResizable:YES];
[text setMinSize: &mf.size];
mf.size.height=mf.size.width=1000000;
[text setMaxSize: &mf.size];
[text setMonoFont: NO];
return TCL_OK;
}
}
ERR("Usage: new text <x> <y> <w> <h> (-window <win>)");
}
int
GUI_newview(Tcl_Interp *interp, int argc, char *argv[])
{
id view;
NXRect mf;
if(argc>= 7)
{
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
if(view=[[[GUI_view alloc] initFrame:&mf] setTheObject: GUI_findobject(interp, ".G0")]) {
SETRES(GUI_newobject(interp, 'v', view));
LOOKFORWINDOW(7, interp->result, view)
[view setVarName: interp->result];
sprintf(GUI_string, "%s.ds", interp->result);
Tcl_SetVar( interp, GUI_string, argv[6], TCL_GLOBAL_ONLY);
return TCL_OK;
}
}
ERR("Usage: new view <x> <y> <w> <h> <drawSelf-proc> (-window <win>)");
}
int
GUI_newscrollview(Tcl_Interp *interp, int argc, char *argv[])
{
id view;
NXRect mf;
if(argc>= 7)
{
id doc;
char *winname=NULL;
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
if(view=[[ScrollView alloc] initFrame:&mf]) {
SETRES(GUI_newobject(interp, 'S', view));
LOOKFORWINDOW(7, interp->result, view)
[view setDocView: doc=GUI_findobject( interp, argv[6])];
if(argc>=9) { if(!strcmp(argv[7], "-window")) winname=argv[8]; }
else winname=Tcl_GetVar( interp, ".curwin", TCL_GLOBAL_ONLY);
if(winname) {
sprintf(GUI_string, ".c%s", winname);
Tcl_SetVar2( interp, GUI_string, argv[6], "", TCL_GLOBAL_ONLY);
}
[view setBorderType: NX_BEZEL];
[view setBackgroundGray: 1];
if([doc isKindOf: [Text class]]) {
[doc setHorizResizable:YES];
[doc sizeToFit];
[doc setHorizResizable:NO];
[doc setBackgroundGray: 1];
}
[view setVertScrollerRequired:YES];
return TCL_OK;
}
}
ERR("Usage: new scrollview <x> <y> <w> <h> <doc-view> (-window <win>)");
}
int
GUI_newimage(Tcl_Interp *interp, int argc, char *argv[])
{
id img;
if(argc>=2)
{
if(img=[NXImage alloc]) {
if(argc>=4 && !strcmp(argv[2], "-load")) {
if([img loadFromFile: argv[3]]) {
SETRES(GUI_newobject(interp, 'i', img));
return TCL_OK;
} else
ERR("new image: couldn't open");
} else {
if(argc>=5 && !strcmp(argv[2], "-size")) {
NXSize s;
s.width=atof(argv[3]);
s.height=atof(argv[4]);
[img setSize: &s];
SETRES(GUI_newobject(interp, 'i', img));
return TCL_OK;
}
}
}
}
ERR("Usage: new image -load <filename>");
}
int
GUI_fromNIB(Tcl_Interp *interp, int argc, char *argv[])
{
id gui;
if(argc>=3)
{
gui=GUI_findobject(interp, ".G0");
[gui setWinsToNil];
if([NXApp loadNibFile: argv[2] owner: gui])
{
[gui lookForWindows];
return TCL_OK;
}
else
ERR("new fromNIB: couldn't load");
}
ERR("Use: new fromNIB <filename>");
}
int
GUI_newslider(Tcl_Interp *interp, int argc, char *argv[])
{
id slider;
NXRect mf;
if(argc>= 10)
{
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
if([[[[[[slider=[Slider alloc] initFrame:&mf] setMinValue: atof(argv[6])] setMaxValue: atof(argv[7])] setStringValue: argv[8]] setTarget:GUI_findobject(interp, ".G0")] setAction:@selector(doSomething:)]) {
SETRES(GUI_newobject(interp, 's', slider));
LOOKFORWINDOW(10, interp->result, slider)
GUI_insertAction( slider, argv[9]);
return TCL_OK;
}
}
ERR("Use: new slider <x> <y> <w> <h> <minVal> <maxVal> <val> <action> (-window <win>)");
}
int
GUI_newbrowser(Tcl_Interp *interp, int argc, char *argv[])
{
id browser;
NXRect mf;
if(argc>= 8)
{
id gui;
char *newname;
mf.origin.x=atof(argv[2]);
mf.origin.y=atof(argv[3]);
mf.size.width=atof(argv[4]);
mf.size.height=atof(argv[5]);
gui=GUI_findobject(interp, ".G0");
if([[[[browser=[NXBrowser alloc] initFrame:&mf] setTarget: gui] setAction:@selector(doSomething:)] setDelegate: gui]) {
SETRES(GUI_newobject(interp, 'B', browser));
LOOKFORWINDOW(8, interp->result, browser)
GUI_insertAction( browser, argv[7]);
sprintf(GUI_string, "%s.list", interp->result);
Tcl_SetVar( interp, GUI_string, argv[6], TCL_GLOBAL_ONLY);
if(newname=malloc(sizeof(char)*(strlen(interp->result)+1))) {
strcpy(newname, interp->result);
NXNameObject(newname, browser, nil);
}
[browser setHorizontalScrollButtonsEnabled: NO];
[browser display];
[browser loadColumnZero];
return TCL_OK;
}
}
ERR("Use: new browser <x> <y> <w> <h> <contents-list> <action> (-window <win>)");
}
/* COMMANDLIST */
struct GUI_cmdo GUI_thecmds[]={
{ "free", GUI_free },
{ "setValue", GUI_setValue },
{ "value", GUI_value },
{ "setImage", GUI_setImage },
{ "display", GUI_display },
{ "lockFocus", GUI_lockFocus },
{ "setDrawSelf", GUI_setDrawSelf },
{ "setMouseDown", GUI_setMouseDown },
{ "setAction", GUI_setAction },
{ "mouseDragging", GUI_mouseDragging },
{ "remove", GUI_remove },
{ "setTitle", GUI_setTitle },
{ "refresh", GUI_refresh },
{ "setMultipleSelection", GUI_setMultipleSelection },
{ "setEmptySelection", GUI_setEmptySelection },
{ "addText", GUI_addText },
{ "setHorizScrolling", GUI_setHorizScrolling },
{ "setVertScrolling", GUI_setVertScrolling },
{ "visibleRect", GUI_visibleRect },
{ "setFont", GUI_setFont },
{ "textLength", GUI_textLength },
{ "sel", GUI_sel },
{ "setSel", GUI_setSel },
{ "getString", GUI_getString },
{ "line2pos", GUI_line2pos },
{ "pos2line", GUI_pos2line },
{ "startDragging", GUI_startDragging },
{ "setDragProc", GUI_setDragProc },
{ "setDragSource", GUI_setDragSource },
{ "composite", GUI_composite },
{ "autosize", GUI_autosize },
{ "orderFront", GUI_orderFront },
{ "select", GUI_select },
{ "hideDisplay", GUI_hideDisplay },
{ "saveAs", GUI_saveAs },
{ "setSize", GUI_setSize },
{ "size", GUI_size },
{ "close", GUI_close },
{ NULL, NULL } };
// types of objects available in the "new" command and corresponding procedures
struct GUI_cmd GUI_thenewcmds[]={
{ "button", GUI_bnew },
{ "textfield", GUI_tnew },
{ "window", GUI_wopen },
{ "view", GUI_newview },
{ "image", GUI_newimage },
{ "slider", GUI_newslider },
{ "browser", GUI_newbrowser },
{ "text", GUI_newtext },
{ "scrollview", GUI_newscrollview },
{ "fromNIB", GUI_fromNIB },
{ NULL, NULL } };
// The class:
@implementation GUI
+ initTCLCommands:(Tcl_Interp *)ip:(id)sender
{
id g;
Tcl_CreateCommand(ip, GUI_cmd_name(ip, "new"),GUI_newCmd,0,NULL);
Tcl_CreateCommand(ip, GUI_cmd_name(ip, "drawPS"),GUI_drawPS,0,NULL);
Tcl_CreateCommand(ip, GUI_cmd_name(ip, "alertPanel"),GUI_alertPanel,0,NULL);
GUI_createGenTable(&GUI_cmds, GUI_thecmds);
GUI_createTable(&GUI_new_cmds, GUI_thenewcmds);
Tcl_InitHashTable(&GUI_actionTable, TCL_ONE_WORD_KEYS);
GUI_newobject(ip, 'G', [g=[GUI alloc] init: ip]);
Tcl_GlobalEval( ip, "\n\
proc _close {w} {\n\
global .c$w\n\
if [info exists .c$w] {\n\
foreach n [array names .c$w] {catch [$n remove]}\n\
unset .c$w\n\
}\n\
}\nproc _newObject {n txt} {global .curwin;global .c${.curwin};set .c${.curwin}($n) 1;set this 1;set l [llength $txt];for {set i 0} {$i<$l} {incr i} {if $this {set this 0;catch {set nxt [lindex $txt [expr $i+1]]};case [lindex $txt $i] drawSelf {$n setDrawSelf $nxt} = {global $nxt;linkVar $nxt $n} action {$n setAction $nxt} name {global $nxt; set $nxt $n} list {global $n.list;set $n.list $nxt} eval {uplevel #0 $nxt}} {set this 1}}}\n\
proc _trc {a b c} {upvar $a u;global _traces; case $c r {set u [$_traces($a) value]} w {$_traces($a) setValue $u}}\n\
proc linkVar {v b} {global _traces $v; set _traces($v) $b; trace variable $v rw _trc}");
return g;
}
- init: (Tcl_Interp *)ipp
{
inp=ipp;
return self;
}
// called by buttons etc., invokes tcl procedure
- doSomething:sender
{
char *action;
if(action=GUI_findAction(sender)) {
if([sender isKindOf:[Control class]]) {
char *val;
if(val=(char *)[sender stringValue]) {
Tcl_SetVar( inp, "_sValue", val, TCL_GLOBAL_ONLY); }
}
Tcl_GlobalEval(inp, action);
}
return self;
}
#define SETVAL(a,b) sprintf(GUI_string, "%g", b); Tcl_SetVar(inp, a, GUI_string, TCL_GLOBAL_ONLY)
- (void)doDrawSelf: (id)view: (NXRect *)re: (NXRect *)bo: (char *)name
{
GUI_therect=re;
SETVAL("_width", bo->size.width);
SETVAL("_height", bo->size.height);
sprintf(GUI_string, "%s.ds", name);
if(name=Tcl_GetVar( inp, GUI_string, TCL_GLOBAL_ONLY))
Tcl_GlobalEval(inp, name);
}
- (void)doMouseDown:(id)view:(NXEvent *)te:(char *)name
{
[view convertPoint: &te->location fromView: nil];
sprintf(GUI_string, "%s.ms", name);
if(name=Tcl_GetVar( inp, GUI_string, TCL_GLOBAL_ONLY))
{
SETVAL("_mx", te->location.x);
SETVAL("_my", te->location.y);
Tcl_GlobalEval(inp, name);
}
}
- takeDrag: (Pasteboard *)pb : (NXPoint *)pt :(char *)name
{
char *data;
int length;
sprintf(GUI_string, "%s.dr", name);
if(name=Tcl_GetVar( inp, GUI_string, TCL_GLOBAL_ONLY))
{
char **tb;
if((tb=(char **)[pb types]) && tb[0]) {
int i=0, ascii=NO;
while(tb[i]) { if(!strcmp(tb[i], NXAsciiPboardType)) {ascii=YES; break; } i++; }
if((ascii && [pb readType: NXAsciiPboardType data: &data length: &length]) || [pb readType: NXFilenamePboardType data: &data length: &length]) {
sprintf(GUI_string, "%g %g", pt->x, pt->y);
Tcl_VarEval( inp, name, " ", GUI_string," {", data, "}", NULL);
[pb deallocatePasteboardData: data length: length];
return self;
}
}
}
return nil;
}
// methods for loading nib files and assigning a tcl object to each interface object in each window
- setWinsToNil
{
win1=win2=win3=win4=win5=win6=win7=win8=win9=win10=nil;
return self;
}
#define L(a) if(a) [self lookInWindow: a]
- lookForWindows
{
L(win1);
L(win2);
L(win3);
L(win4);
L(win5);
L(win6);
L(win7);
L(win8);
L(win9);
L(win10);
return self;
}
- convertToGUIview: (id)view
{
char *txt;
if((txt=(char *)NXGetObjectName(view)) && txt[0]!=0) {
NXRect theframe;
id gview;
char *newname;
[view getFrame: &theframe];
if(gview=[[[GUI_view alloc] initFrame:&theframe] setTheObject: GUI_findobject(inp, ".G0")]) {
newname=GUI_newobject(inp, 'v', gview);
[[view superview] addSubview: gview];
[gview setVarName: newname];
Tcl_VarEval(inp, "_newObject ", newname, " {", NXGetObjectName(view), "}", NULL);
}
[view free];
}
return self;
}
- lookIntoView: (id)view
{
int i;
id list;
list=[view subviews];
printf("inView %d\n", [list count]);
for(i=[list count]-1; i>=0; i--) [self lookInView: [list objectAt:i]];
return self;
}
- lookInView: (id)view
{
char *thename=NULL;
char *oname;
oname=(char *)NXGetObjectName(view);
if([view isKindOf: [Button class]]) thename=GUI_newobject(inp, 'b', view); else
if([view isKindOf: [TextField class]]) thename=GUI_newobject(inp, 't', view); else
if([view isKindOf: [Slider class]]) thename=GUI_newobject(inp, 's', view); else
if([view isKindOf: [Text class]]) { thename=GUI_newobject(inp, 'T', view); if(!oname) oname=(char *)NXGetObjectName([[view superview] superview]); } else
if([view isKindOf: [ScrollView class]]) { thename=GUI_newobject(inp, 'S', view); return [self lookInView:[view docView]]; } else
if([view isMemberOf: [View class]]) return([self convertToGUIview: view]); else
if([view isKindOf: [Box class]]) return [self lookIntoView: [[view subviews] objectAt: 0]]; else
if([view isKindOf: [Matrix class]]) thename=GUI_newobject(inp, 'm', view); else
if([view isKindOf: [NXBrowser class]]) {
char *newname;
id gui;
thename=GUI_newobject(inp, 'B', view);
if(newname=malloc(sizeof(char)*(strlen(thename)+1))) {
strcpy(newname, thename);
NXNameObject(newname, view, nil);
gui=GUI_findobject(inp, ".G0");
[view setDelegate: gui];
}
}
else
return self;
Tcl_VarEval(inp, "_newObject ", thename, " {", oname, "}", NULL);
return self;
}
- lookInWindow: (id)win
{
Tcl_SetVar( inp, ".curwin", GUI_newobject(inp, 'w', win), TCL_GLOBAL_ONLY);
Tcl_VarEval( inp, "lappend _newwins ${.curwin}", NULL);
[self lookIntoView: [win contentView]];
return self;
}
// Thanks to Jeff Martin for his StringList example...
- (int)browser:sender fillMatrix:matrix inColumn:(int)column
{
int i;
id cellList, theCell;
int count;
char **argvp;
char *name;
name=(char *)NXGetObjectName(sender);
sprintf(GUI_string, "%s.list", name);
if(name=Tcl_GetVar( inp, GUI_string, TCL_GLOBAL_ONLY))
{
if(name=Tcl_GetVar( inp, name, TCL_GLOBAL_ONLY))
{
// split string "name" into string array argvPtr
Tcl_SplitList( inp, name, &count, &argvp);
// Set matrix to have the right number of cells.
[matrix renewRows:count cols:1];
// Get list of cells from the matrix.
cellList = [matrix cellList];
// For each cell set its value, set whether it is a leaf or not and
// mark it loaded.
for(i=0;i<[cellList count];i++) {
theCell = [cellList objectAt:i];
[theCell setStringValue:argvp[i]];
[theCell setLeaf:YES];
[theCell setLoaded:YES];
}
free(argvp);
// Return the number of rows.
return count;
}
}
return 0;
}
- windowWillClose: sender
{
return [self doSomething: sender];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.