📄 gobject.c
字号:
if (IsView(o1)) { if (((VIEW) o1)->flagReverse & YFlagReverse) signH -=signH; if (((VIEW) o1)->flagReverse & XFlagReverse) signW -=signW; } } /* Convert the rectangle from regular to generalized */ Rect2GRect(&mx,&my,&mw,&mh,rectType,signW,signH); /* We convert each extremity of the rectangle */ Global2Local(o,mx,my,x,y); Global2Local(o,mx+mw,my+mh,w,h); *w -= *x; *h -= *y; if (*w < 0) { *x += *w; *w = -*w; } if (*h < 0) { *y += *h; *h = -*h; }}/* * Update the local rect of an object from its global rect */void UpdateLocalRectGObject(GOBJECT o){ Global2LocalRect((GOBJECT) (o->father),o->x,o->y,o->w,o->h,&(o->rx),&(o->ry),&(o->rw),&(o->rh),o->rectType);}/* Update the global rect of an object from its local rect */void UpdateGlobalRectGObject(GOBJECT o){ Local2GlobalRect((GOBJECT) (o->father),o->rx,o->ry,o->rw,o->rh,o->rectType,&(o->x),&(o->y),&(o->w),&(o->h));}/********************************************************************************** * * Some other misc functions * **********************************************************************************//* Get the name of an object (returns a temporary string) */char *GetNameGObject(GOBJECT o){ GOBJECT array[200]; char *name; int s,i,n; n = 0; s = 0; while (o != NULL) { array[n++] = o; s += strlen(o->name); o = (GOBJECT) o->father; } name = CharAlloc(s+n); TempStr(name); name[0] = '\0'; for(i=n-1;i>=0;i--) { strcat(name,array[i]->name); if (i != 0) strcat(name,"."); } return(name);}/* * Compute the positions (absolute and relative) of an object using its grid position */static void ComputeGridRect(GOBJECT obj){ GRID grid; int x,y,w,h,xGrid,yGrid; int dx,dy; char *l[4]; char str1[20],str2[20]; /* Basic checking */ if (!IsSubClass(obj->father->gclass,theGridClass)) Errorf("ComputeGridRect() : Weird error 1"); grid = (GRID) obj->father; /* More checking */ if (!(obj->flagGrid)) Errorf("ComputeGridRect() : Weird error 2"); /* Get the absolute position of the grid */ if (IsWin((GOBJECT) grid)) { xGrid = 0; yGrid = 0; } else { xGrid = grid->x; yGrid = grid->y; } /* Compute the number of pixels for a grid unit */ dx = (int) ((grid->w-grid->leftMargin-grid->rightMargin+grid->dx)/((LWFLOAT) grid->gridM)-grid->dx+.5); dy = (int) ((grid->h-grid->topMargin-grid->bottomMargin+grid->dy)/((LWFLOAT) grid->gridN)-grid->dy+.5); if (dx <=0) dx = 1; if (dy <=0) dy = 1; /* Compute the absolute position of the object */ x = xGrid + grid->leftMargin + (obj->i-1)*(dx+grid->dx); y = yGrid + grid->topMargin + (obj->j-1)*(dy+grid->dy); /* Compute the size of the object */ w = obj->m*(dx+grid->dx)-grid->dx; h = obj->n*(dy+grid->dy)-grid->dy; /* If it is the last object of a row or column, we must correct the size so that it fits the grid */ if (obj->i+obj->m-1 == grid->gridM) w = xGrid+grid->w-grid->rightMargin-x; if (obj->j+obj->n-1 == grid->gridN) h = yGrid+grid->h-grid->bottomMargin-y; if (w <= 0) w = obj->m*dx +1; if (h <= 0) h = obj->n*dy +1; /* Then we set the position MERDE */ sprintf(str1,"%d",x); sprintf(str2,"%d",y); l[0] = "-apos"; l[1] = str1; l[2] = str2; l[3] = NULL; SetGObject(obj,l,NO); /* Then we set the size MERDE */ sprintf(str1,"%d",w); sprintf(str2,"%d",h); l[0] = "-asize"; l[1] = str1; l[2] = str2; l[3] = NULL; SetGObject(obj,l,NO);}/* * Send (varcontent) message to a gobject (from a hash table ONLY !) * Actually, this routine should never be called ! */static void * SendMessage2AGObject(void *content,int message,void **arg){ Errorf("SendMessage2AGObject() : Weired error"); return(NULL);}/*************************************************** * * * (Des)Allocation of gobjects functions * * ***************************************************/ /* * Function for creating a gobject named 'name' of a given 'class' and adding it to the glist 'father'. * 'argv' is a list of optional initialization fields that will be set after creating the gobject. * 'flagDraw' indicates whether the newly created object must be drawn or not */GOBJECT NewGObject(GCLASS class, GLIST father, char *name, char **argv,char flagDraw){ GOBJECT o; GCLASS c[MaxClassHierarchyDepth]; char flagWindow; int n; /* Is the class a window class ? */ flagWindow = IsSubClass(class,theWindowClass); /* Cannot specify a father for a window */ if (flagWindow && father != NULL) Errorf("NewGObject() : Cannot specify a father for a window"); /* Must specify a father for non window */ if (!flagWindow && father == NULL) Errorf("NewGObject() : Must specify a father for a gobject which is not a window"); /* Print a warning if the object already exists */ if (father != NULL && (o = (GOBJECT) GetElemHashTable(father->theGObjects,name)) != NULL) { if (DeleteGObject(o) == NO) { Warningf("Cannot add object '%s' in glist '%s' since object with the same name already exists and is protected",name,father->name); return(NULL); } else Warningf("Adding object '%s' (which already exists) in glist '%s' -> delete former version",name,father->name); } /* Alloc the object */ #ifdef DEBUGALLOCDebugType = "GObject";#endif o = (GOBJECT) Malloc(class->nbBytes); InitValue(o,NULL); o->nRef = 0; /* Copying the name */ o->name = CopyStr(name); /* Setting the class */ o->gclass = class; /* Adding the object to the 'father' */ o->father = NULL; o->front = NULL; o->sendMessage = SendMessage2AGObject; if (father != NULL) AddGObject2GList(o,father); /* Get the class hierarchy in the c array */ n = 0; c[n] = class; while (c[n]->fatherClass != NULL) { c[n+1] = c[n]->fatherClass; n++; } /* Perform the initializations : from the top class initialization to the initialization of the 'class' */ for (;n>=0;n--) { o->classCur = c[n]; if (c[n]->init) (*(c[n]->init))(o); if (c[n]->msgeSCommand != NULL) DoScriptListv(o,c[n]->msgeSCommand,"init",NULL,-1); } /* Optional initializations of fields */ o->classCur = o->gclass; SetGObject(o,argv,NO); /* Draw the gobject if asked */ o->classCur = o->gclass; if (flagDraw) DrawWholeGObject(o,YES); /* Then return */ return(o);}/* * Basic Function to delete the gobject 'o' (not to be called directly) * * No hiding is performed before * * It returns YES if deletion was made and NO if not * (NOTA : for now the o->nRef is never greater than 1 thus deletion is always performed when * this function is called) */static void RemoveGUpdate(GOBJECT o);static char DeleteGObject_(GOBJECT o){ struct event event; GCLASS class; GLIST list; WINDOW w,w1; int r; AHASHELEM e; GOBJECT obj; /* If there still exists a reference then return otherwise we have to destroy the gobject */ if (o->nRef > 1) { o->nRef--; return(NO); } /* Force the classCur of the object to be its class */ o->classCur = o->gclass; /* We first send all the delete events */ class = o->gclass; while (class != NULL) { o->classCur = class; event.object = o; event.type = Del; SendEvent(&event); /* Then loop on the class */ class = class->fatherClass; } o->classCur = o->gclass; /* If it is a GLIST then we MUST delete all the gobjects in it first (because they might adress the GList) */ if (IsGList(o)) { list = (GLIST) o; /* We loop on the gobjects */ for (r = 0; r<list->theGObjects->nRows;r++) { for (e = list->theGObjects->rows[r]; e != NULL;) { obj = (GOBJECT) e; e = e->next; obj->flagHide = YES; DeleteGObject_(obj); } } list->theGObjects->nElems = 0; } /* We perform deletion methods from the class of the object to the topclass */ class = o->gclass; while (class != NULL) { /* Then call the specific script delete method if any */ if (class->msgeSCommand != NULL) DoScriptListv(o,class->msgeSCommand,"delete",NULL,NO); /* Then call the specific delete function if any */ if (class->deleteContent) (*(class->deleteContent))(o); /* Then loop on the class */ class = class->fatherClass; } o->classCur = o->gclass; /* We must remove the gobject from the update list if it is in it */ RemoveGUpdate(o); /* Remove the object from its father GList */ if (o->father != NULL) { RemoveGObject2GList(o,o->father); o->father = NULL; } /* If it is a window then we remove it from the window hash table */ if (IsWin(o)) { GetRemoveElemHashTable(theWindowsHT,o->name); w = (WINDOW) o; if (theWindows == w) theWindows = (WINDOW) w->front; else { w1 = theWindows; while(w1->front != o) w1 = (WINDOW) w1->front; w1->front = w->front; w->front = NULL; } } /* Then free the non specific content of the object */ Free(o->name); /* Then the object */ #ifdef DEBUGALLOCDebugType = "GObject";#endif Free(o); return(YES);}/* * Function to delete the gobject 'o' after hiding it * * Before trying to delete it, it notifies its glist that it will be * deleted. If the notify method sends back YES, then deletion is allowed * otherwise it is not allowed and the object is not deleted. */char DeleteGObject(GOBJECT o){ GCLASS class; LISTV lv; /* This line is useless for now since the 'nRef' field is never greater than 1 */ if (o->nRef > 1) return(DeleteGObject_(o)); /* If the object is not a window we must notify the glist it belongs to */ if (!IsWin(o)) { /* The notification method is sent to the father and is inherited thus we must loop on the top classes */ class = o->father->gclass; while (class != NULL) { /* Then call the specific script deleteNotify method if any */ if (class->msgeSCommand != NULL) { lv = TNewListv(); AppendStr2Listv(lv,o->name); DoScriptListv((GOBJECT) o->father,class->msgeSCommand,"deleteNotify",lv,YES); if (toplevelCur->flagReturn) { /* if it returned 0 then we forbid deletion ?????? */ if (GetResultType() == numType && GetResultFloat() == 0); /* Otherwise let's do the deletion */ break; } } /* Then call the specific deleteNotify function if any */ if (class->deleteNotify) { if ((*(class->deleteNotify))((GOBJECT) o->father) == 0) return(NO); break; } /* Then loop on the class */ class = class->fatherClass; } } HideGObject(o); return(DeleteGObject_(o));}/*************************************************** * * * Drawing functions * * ***************************************************//* * Basic function to draw the object 'o' in the window 'win' * (that is the window 'o' is displayed in) and only in the * rectangle specified by x,y,w,h. * Just the object 'o' is drawn. No other objects are redrawn (event those in front of 'o'). */static void DrawGObject_(WINDOW win, GOBJECT o, int x,int y,int w,int h){ LWFLOAT lx,ly,lw,lh; struct event event; GCLASS class,class1; WINDOW clipWin; int clipX,clipY,clipW,clipH; FONT font; /* If window or object is hidden then return */ if (win->flagHide) return; if (o->flagHide) return; /* Get the current class of the object */ class = o->classCur; /* If rect empty then return */ if (w <= 0 || h <= 0) return; /* Get the current clip rect and set it to the new one */ WGetClipRect(&clipWin,&clipX,&clipY,&clipW,&clipH); WSetClipRect(win, x, y, w, h); /* Clear the corresponding rect */ WClearRect((GOBJECT) win,o->bgColor,x,y,w,h,YES,NormalRect); /* Set some graphic attributes */ WSetColor(win,o->fgColor); font = WGetFont(win); WSetFont(win,o->font); WSetLineStyle(win,o->lineStyle); WSetPenMode(win,o->penMode); WSetPenSize(win,o->penSize); /* Remember the last window we drawn into */ toplevelCur->lastWindow = win; /* Local coordinates of the rectangle */ Global2LocalRect(o,x,y,w,h,&lx,&ly,&lw,&lh,NormalRect); /* We must find the first drawing method in the class hierarchy */ class1 = class; while (class1 != NULL) { /* DrawMessage */ if (DrawMessage(o,win,class1,x,y,w,h)) break; class1 = class1->fatherClass; } /* Send a draw event */ event.object = o; event.object->classCur = class; event.type = Draw; event.x = lx; event.y = ly; event.w = lw; event.h = lh; event.i = x; event.j = y; event.m = w;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -