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.