#include //Gui system - object system + graphic #include "types.h" #include #include #include "memman.h" #include "event.h" #include "devices.h" #include "bmouse.h" #include "bgraph.h" #include "gui.h" #include #define E_REDRAW_DESKTOP 2010 #define E_REDRAW_WINDOW 2000 void *gui_background=NULL; extern T_EVENT_ROOT *ev_tree; WINDOW *desktop={NULL},*waktual={NULL};; OBJREC *o_aktual={NULL},*o_end={NULL},*o_start={NULL}; CTL3D noneborder={0,0,0,0}; FC_TABLE f_default; word desktop_y_size; char force_redraw_desktop=0; static char change_flag=0,f_cancel_event=0; const word *default_font; void empty(void) { } void empty1(OBJREC *o) { o; } void empty2_p(OBJREC *o, va_list _) { o; } void empty3(EVENT_MSG *ms,OBJREC *o) { o;ms; } void empty2(int x1,int y1,int x2,int y2,OBJREC *o) { o;x1;y1;x2;y2; } void draw_border(integer x,integer y,integer xs,integer ys,CTL3D *btype) { word i,j,c; c=curcolor; j=btype->ctldef; for (i=0;ibsize;i++) { x--;y--;xs+=2;ys+=2; if (j & 1) curcolor=btype->shadow; else curcolor=btype->light; hor_line32(x,y,xs+x); ver_line32(x,y,ys+y); if (j & 1) curcolor=btype->light; else curcolor=btype->shadow; hor_line32(x,y+ys,xs+x); ver_line32(x+xs,y,ys+y); j>>=1; } curcolor=c; } void check_window(WINDOW *w) { if (w->x<=w->border3d.bsize) w->x=w->border3d.bsize; if (w->y<=w->border3d.bsize) w->y=w->border3d.bsize; if (w->x>=SCR_WIDTH_X-w->border3d.bsize-w->xs) w->x=SCR_WIDTH_X-w->border3d.bsize-w->xs-1; if (w->y>=desktop_y_size-w->border3d.bsize-w->ys) w->y=desktop_y_size-w->border3d.bsize-w->ys-1; } void show_window(WINDOW *w) { int ok; ok=w->border3d.bsize; showview(w->x-ok,w->y-ok,w->xs+(ok<<1),w->ys+(ok<<1)); } void draw_cl_window(WINDOW *o) { curcolor=o->color; bar32(o->x,o->y,o->x+o->xs,o->y+o->ys); draw_border(o->x,o->y,o->xs,o->ys,&o->border3d); } WINDOW *create_window(int x,int y, int xs, int ys, word color, CTL3D *okraj) { WINDOW *p; p=(WINDOW *)getmem(sizeof(WINDOW)); p->x=x;p->y=y;p->xs=xs;p->ys=ys; p->color=color;memcpy(&(p->border3d),okraj,sizeof(CTL3D)); p->objects=NULL; p->modal=0; p->popup=0; p->minimized=0; p->window_name=NULL; p->minsizx=MINSIZX; p->minsizy=MINSIZY; p->idlist=NULL; p->draw_event=draw_cl_window; check_window(p); return p; } int send_lost() { EVENT_MSG msg; msg.msg=E_LOST_FOCUS; if (o_aktual!=NULL) { o_aktual->on_exit(); if (f_cancel_event) return -1; o_aktual->call_event(&msg,o_aktual); o_aktual=NULL; } return 0; } void select_window(int32_t id) { WINDOW *p,*q; if (waktual->id==id) return; if (waktual->modal) return; if (send_lost()) return; p=desktop; while (p!=NULL && p->id!=id) p=p->next; if (p==NULL) return; q=desktop; if (p!=desktop) { while (q->next!=p) q=q->next; q->next=p->next; } else { desktop=p->next; } p->next=NULL; waktual->next=p; waktual=p; if (waktual->objects!=NULL) { o_start=waktual->objects; o_aktual=NULL; o_end=o_start; while(o_end->next!=NULL) o_end=o_end->next; } else {o_start=NULL;o_aktual=NULL;o_end=NULL;} } int32_t desktop_add_window(WINDOW *w) { static int32_t id_counter=0; w->id=id_counter++; w->next=NULL; if (desktop==NULL) { waktual=w; desktop=w; } else { if (o_aktual!=NULL) { EVENT_MSG msg; msg.msg=E_LOST_FOCUS; o_aktual->on_exit(); o_aktual->call_event(&msg,o_aktual); } waktual->next=w; waktual=w; } o_aktual=NULL; o_end=NULL; o_start=NULL; return w->id; } WINDOW *find_window(int32_t id) { WINDOW *p; p=desktop; while (p!=NULL && p->id!=id) p=p->next; return p; } void absolute_window(WINDOW *w,OBJREC *o, int *x, int *y) { switch (o->align) { case 0: case 1:*y=o->y+w->y;break; case 2: case 3:*y=(w->y+w->ys)-(o->y+o->ys);break; } switch (o->align) { case 0: case 3:*x=o->x+w->x;break; case 1: case 2:*x=(w->x+w->xs)-(o->x+o->xs);break; } } void disable_bar(int x,int y,int xs,int ys,word color) { int i,j; word *a; int32_t scr_linelen2 = GetScreenPitch(); for (i=y;i<=y+ys;i++) { a=GetScreenAdr()+scr_linelen2*i+x; for(j=x;j<=x+xs;j++) { *a=((*a & RGB555(30,30,30))+(color & RGB555(30,30,30)))>>1; *a=((*a & RGB555(30,30,30))+(color & RGB555(30,30,30)))>>1; a++; } } } void draw_object(WINDOW *w,OBJREC *o,char show) { int x = 0, y = 0; int ok; // WINDOW *ws; if (o->draw_error==1) return; o->draw_error=1; ok=w->border3d.bsize; absolute_window(w,o,&x,&y); o->locx=x;o->locy=y; if (o->xs<1 || o->ys<1) { o->draw_error=0; return; } schovej_mysku(); draw_border(x,y,o->xs,o->ys,&o->border3d); curcolor=o->color; curfont=o->font;position(x,y); memcpy(&charcolors,&o->f_color,sizeof(charcolors)); // ws=waktual; // waktual=w; o->call_draw(x,y,x+o->xs,y+o->ys,o); // waktual=ws; if (!o->enabled) disable_bar(x,y,o->xs,o->ys,o->color); ukaz_mysku(); if (show) showview(x-ok,y-ok,o->xs+(ok<<1),o->ys+(ok<<1)); o->draw_error=0; } void redraw_object(OBJREC *o) { draw_object(waktual,o,1); } void redraw_window_call() { OBJREC *p; schovej_mysku(); waktual->draw_event(waktual); p=waktual->objects; while (p!=NULL) { draw_object(waktual,p,0); p=p->next; } ukaz_mysku(); show_window(waktual); return; } void add_to_idlist(OBJREC *o) { TIDLIST *p,*q; p=(TIDLIST *)getmem(sizeof(TIDLIST)); p->obj=o; if (waktual->idlist==NULL) { p->next=NULL; waktual->idlist=p; return; } if (((waktual->idlist)->obj)->id>o->id) { p->next=waktual->idlist; waktual->idlist=p; return; } q=waktual->idlist; while (q->next!=NULL && ((q->next)->obj)->idid) q=q->next; p->next=q->next; q->next=p; } void define(int id,int x,int y,int xs,int ys,char align,void (*initproc)(OBJREC *),...) { OBJREC *o; o=(OBJREC *)getmem(sizeof(OBJREC)); o->x=x;o->y=y;o->xs=xs;o->ys=ys; o->id=id; o->call_init=empty2_p; o->call_draw=empty2; o->call_event=empty3; o->call_done=empty1; o->autoresizex=0; o->autoresizey=0; o->on_event=empty3; o->on_enter=empty; o->on_exit=empty; o->on_change=empty; o->enabled=1; o->draw_error=0; o->color=waktual->color;memcpy(o->f_color,f_default,sizeof(f_default)); memcpy(&(o->border3d),&noneborder,sizeof(CTL3D)); o->userptr=NULL; o->align=align; o->font=default_font; o->datasize=0; initproc(o); if (o->datasize) { o->data=(void *)getmem(o->datasize); memset(o->data,0,o->datasize); }else { o->data=NULL; } va_list vlst; va_start(vlst, initproc); o->call_init(o,vlst); va_end(vlst); if (o->datasize && o->data==NULL) o->data=(void *)getmem(o->datasize); o->next=NULL; if (o_start==NULL) { o_start=o; o_end=o; o_aktual=NULL; waktual->objects=o; } else { o_end->next=o; o_end=o; } add_to_idlist(o); } CTL3D *border(word light,word shadow, word bsize, word btype) { static CTL3D p; p.light=light;p.shadow=shadow;p.bsize=bsize;p.ctldef=btype; return &p; } void property(CTL3D *ctl,const word *font,FC_TABLE *fcolor,word color) { if (ctl!=NULL) memcpy(&o_end->border3d,ctl,sizeof(CTL3D)); if (font!=NULL) o_end->font=font; if (fcolor!=NULL) memcpy(&o_end->f_color,fcolor,sizeof(FC_TABLE)); if (color!=0xffff) o_end->color=color; } FC_TABLE *flat_color(word color) { static FC_TABLE p; p[0]=0xffff; p[1]=color;p[2]=color;p[3]=color;p[4]=color;p[5]=color;p[6]=color; return &p; } void aktivate_window(MS_EVENT *ms) { WINDOW *p,*q; if (ms->event_type==1) return; p=desktop;q=NULL; while (p!=NULL) { if (ms->x>=p->x && ms->x<=p->x+p->xs && ms->y>=p->y && ms->y<=p->y+p->ys) q=p; p=p->next; } if (q==NULL) return; if (q!=waktual) { select_window(q->id); redraw_window(); return; } return; } void redraw_desktop_call(EVENT_MSG *msg,void **data) { WINDOW *w; char *oz; data; if (msg->msg==E_INIT || msg->msg==E_DONE) return; if (!force_redraw_desktop) return; force_redraw_desktop=0; schovej_mysku(); if (gui_background==NULL) { curcolor=DESK_TOP_COLOR; bar32(0,0,SCR_WIDTH_X,SCR_WIDTH_Y-1); } else put_picture(0,0,gui_background); oz=otevri_zavoru; do_events(); *oz=1; w=desktop; while (w!=NULL) { OBJREC *p; w->draw_event(w); p=w->objects; while (p!=NULL) { draw_object(w,p,0); p=p->next; } w=w->next; *oz=0; do_events(); *oz=1; } send_message(E_REDRAW); ukaz_mysku(); showview(0,0,0,0); move_ms_cursor(0,0,1); } void redraw_desktop() { force_redraw_desktop=1; } void redraw_window() { redraw_window_call(); } void close_window(WINDOW *w) { WINDOW *p; OBJREC *q; if (waktual==w && send_lost()) return; if (w==waktual && waktual!=desktop) { p=desktop; while (p->next!=waktual) p=p->next; w->modal=0; select_window(p->id); } if (w!=desktop) { p=desktop; while (p->next!=w) p=p->next; p->next=w->next; } else { desktop=w->next; if (desktop==NULL) waktual=NULL; } while (w->objects!=NULL) { q=w->objects; w->objects=q->next; q->call_done(q); if (q->userptr!=NULL) free(q->userptr); if (q->data!=NULL) free(q->data); free(q); } while (w->idlist!=NULL) { TIDLIST *p; p=w->idlist; w->idlist=p->next; free(p); } free(w); if (desktop==NULL) exit_wait=1; redraw_desktop(); } //-------------------------------- GUI EVENTS ------------------------- char mouse_in_object(MS_EVENT *ms,OBJREC *o, WINDOW *w) { int x1=0, y1=0, x2=0, y2=0; absolute_window(w,o,&x1,&y1); x2=x1+o->xs; y2=y1+o->ys; if (ms->x>=x1 && ms->x<=x2 && ms->y>=y1 && ms->y<=y2) return 1; else return 0; } OBJREC *get_last_id() { TIDLIST *p; p=waktual->idlist; while (p->next!=NULL) p=p->next; return p->obj; } OBJREC *get_next_id(OBJREC *o) { TIDLIST *p; p=waktual->idlist; while (p!=NULL && p->obj!=o) p=p->next; if (p==NULL) return NULL; do { p=p->next; if (p==NULL) p=waktual->idlist; o=p->obj; if (o->enabled && o->call_event!=empty3) return o; } while (1); } OBJREC *get_prev_id(OBJREC *o) { TIDLIST *p,*q; p=waktual->idlist; while (p!=NULL && p->obj!=o) p=p->next; if (p==NULL) return NULL; do { if (p==waktual->idlist) { p=waktual->idlist; while (p->next!=NULL) p=p->next; } else { q=waktual->idlist; while (q->next!=p) q=q->next; p=q; } o=p->obj; if (o->enabled && o->call_event!=empty3) return o; } while (1); } void do_it_events(EVENT_MSG *msg,void **user_data) { MS_EVENT *msev; EVENT_MSG msg2; char b; static word cursor_tick=CURSOR_SPEED OBJREC *p; char *oz=otevri_zavoru; user_data; if (msg->msg==E_INIT) return; if (desktop==NULL) {exit_wait=1;return;} change_flag=0;f_cancel_event=0; if (o_aktual!=NULL) { EVENT_MSG mcpy = clone_message(msg); o_aktual->on_event(&mcpy,o_aktual); destroy_message(&mcpy); } if (msg->msg==E_MOUSE) { *oz=1; EVENT_MSG fwmsg = clone_message(msg); fwmsg.msg = msg->msg; va_copy(fwmsg.data, msg->data); msev=get_mouse(msg); aktivate_window(msev); if (o_aktual == NULL) { if (o_start != NULL && (msev->tl1 || msev->tl2 || msev->tl3)) { o_aktual = o_start; while (o_aktual != NULL && (!o_aktual->enabled || !mouse_in_object(msev, o_aktual, waktual) || o_aktual->call_event == empty3)) o_aktual = o_aktual->next; if (o_aktual != NULL) { msg2.msg = E_GET_FOCUS; o_aktual->call_event(&msg2, o_aktual); o_aktual->on_enter(); o_aktual->call_event(&fwmsg, o_aktual); } } } else { if (o_aktual->enabled) { b = mouse_in_object(msev, o_aktual, waktual); } else { b = 0; } if (b) { o_aktual->call_event(&fwmsg, o_aktual); } if ((msev->tl1 || msev->tl2 || msev->tl3) && !b) { o_aktual->on_exit(); if (f_cancel_event) return; msg2.msg = E_LOST_FOCUS; o_aktual->call_event(&msg2, o_aktual); p = o_start; while (p != NULL && (!p->enabled || !mouse_in_object(msev, p, waktual) || p->call_event == empty3)) p = p->next; if (p != NULL) { o_aktual = p; } msg2.msg = E_GET_FOCUS; o_aktual->call_event(&msg2, o_aktual); o_aktual->on_enter(); if (p != NULL) o_aktual->call_event(&fwmsg, o_aktual); } } destroy_message(&fwmsg); } if (msg->msg==E_KEYBOARD) { *oz=1; EVENT_MSG cmsg = clone_message(msg); if (o_aktual!=NULL) { o_aktual->call_event(msg,o_aktual); } int code = va_arg(cmsg.data, int); destroy_message(&cmsg); if ((code>>8)==0xf && waktual->idlist!=NULL) { if (o_aktual==NULL) o_aktual=get_last_id(); if (o_aktual!=NULL) { f_cancel_event=0; o_aktual->on_exit(); if (f_cancel_event) return; msg2.msg=E_LOST_FOCUS; o_aktual->call_event(&msg2,o_aktual); } if((code & 0xff)==9) o_aktual=get_next_id(o_aktual); else o_aktual=get_prev_id(o_aktual); if (o_aktual!=NULL) { msg2.msg=E_GET_FOCUS; o_aktual->call_event(&msg2,o_aktual); o_aktual->on_enter(); } } } if (msg->msg==E_TIMER && o_aktual!=NULL) { o_aktual->call_event(msg,o_aktual); if (!(cursor_tick--)) { msg->msg=E_CURSOR_TICK; o_aktual->call_event(msg,o_aktual); o_aktual->on_event(msg,o_aktual); cursor_tick=CURSOR_SPEED; } } if (msg->msg==E_GUI) { OBJREC *o; EVENT_MSG msg2 = clone_message(msg); int control = va_arg(msg->data, int); msg->msg = va_arg(msg->data, int); o=find_object(waktual,control); if (o!=NULL) { EVENT_MSG msg3 = clone_message(msg); o->call_event(&msg2,o); o->on_event(&msg3,o_aktual); destroy_message(&msg3); } destroy_message(&msg2); } if (msg->msg==E_CHANGE) run_background(o_aktual->on_change); if (change_flag) send_message(E_CHANGE); } void install_gui(void) { desktop_y_size = SCR_WIDTH_Y; send_message(E_ADD,E_MOUSE,do_it_events); send_message(E_ADD,E_KEYBOARD,do_it_events); send_message(E_ADD,E_CHANGE,do_it_events); send_message(E_ADD,E_TIMER,do_it_events); send_message(E_ADD,E_GUI,do_it_events); send_message(E_ADD,E_IDLE,redraw_desktop_call); } void uninstall_gui(void) { send_message(E_DONE,E_MOUSE,do_it_events); send_message(E_DONE,E_KEYBOARD,do_it_events); send_message(E_DONE,E_CHANGE,do_it_events); send_message(E_DONE,E_TIMER,do_it_events); send_message(E_DONE,E_GUI,do_it_events); send_message(E_DONE,E_IDLE,redraw_desktop_call); } //send_message(E_GUI,cislo,E_UDALOST,data....) void on_control_change(void (*proc)(void)) { o_end->on_change=proc; } void on_control_enter(void (*proc)(void)) { o_end->on_enter=proc; } void on_control_exit(void (*proc)(void)) { o_end->on_exit=proc; } void on_control_event(void (*proc)(EVENT_MSG *msg, struct objrec *)) { o_end->on_event=proc; } void terminate_gui(void) { exit_wait=1; } void set_change(void) { change_flag=1; } void set_window_modal(void) { waktual->modal=1; } void set_object_value(char redraw,OBJREC *o,void *value) { if (memcmp(o->data,value,o->datasize)) { memcpy(o->data,value,o->datasize); if (redraw) redraw_object(o); } } OBJREC *find_object(WINDOW *w,int id) { OBJREC *p; p=w->objects; if (p==NULL) return NULL; while (p!=NULL && p->id!=id) p=p->next; return p; } OBJREC *find_object_desktop(int win_id,int obj_id,WINDOW **wi) { WINDOW *w; OBJREC *o; if (win_id<0) return NULL; if (win_id==0) w=waktual; else w=find_window(win_id); if (w==NULL) return NULL; o=find_object(w,obj_id); *wi=w; return o; } void set_value(int win_id,int obj_id,void *value) { OBJREC *o; WINDOW *w; if ((o=find_object_desktop(win_id,obj_id,&w))==NULL)return; set_object_value((w==waktual),o,value); } void set_default(void *value) { set_object_value(0,o_end,value); } void goto_control(int obj_id) { EVENT_MSG msg; if (send_lost()) return; o_aktual=find_object(waktual,obj_id); msg.msg=E_GET_FOCUS; o_aktual->on_event(&msg,o_aktual); o_aktual->call_event(&msg,o_aktual); } void c_set_value(int win_id,int obj_id,int cnst) { OBJREC *o; WINDOW *w; if ((o=find_object_desktop(win_id,obj_id,&w))==NULL)return; set_object_value((w==waktual),o,&cnst); } void c_default(int cnst) { set_object_value(0,o_end,&cnst); } int f_get_value(int win_id,int obj_id) { OBJREC *o; WINDOW *w; int v; if ((o=find_object_desktop(win_id,obj_id,&w))==NULL) return 0; memcpy(&v,o->data,o->datasize); return v; } void get_value(int win_id,int obj_id,void *buff) { OBJREC *o; WINDOW *w; if ((o=find_object_desktop(win_id,obj_id,&w))==NULL)return; memcpy(buff,o->data,o->datasize); } void cancel_event() { f_cancel_event=1; } void set_enable(int win_id,int obj_id,int condition) { OBJREC *o; WINDOW *w; condition=(condition!=0); if ((o=find_object_desktop(win_id,obj_id,&w))==NULL) return; if (o==o_aktual) { if (send_lost()) return; } else { o_aktual=NULL; } if (o->enabled!=condition) { o->enabled=condition; if (w==waktual) redraw_object(o); } } void close_current() { close_window(waktual); } typedef void (*PROG)(void); void background_runner(EVENT_MSG *msg,void **prog) { PROG *prog_ptr = (PROG *)(prog); if (msg->msg==E_INIT) { *prog_ptr = va_arg(msg->data, PROG); return; } if (msg->msg==E_DONE) { *prog_ptr=NULL; return; } (*prog_ptr)(); msg->msg=-2; } void run_background(PROG p) { send_message(E_ADD,E_IDLE,background_runner,p); } void movesize_win(WINDOW *w, int newx,int newy, int newxs, int newys) { int xsdif,ysdif; OBJREC *p; if (newxsminsizx) newxs=w->minsizx; if (newysminsizy) newys=w->minsizy; if (newxs>=(SCR_WIDTH_X-2*w->border3d.bsize)) newxs=(SCR_WIDTH_X-2*w->border3d.bsize)-1; if (newys+2>=(desktop_y_size-2*w->border3d.bsize)) newys=(desktop_y_size-2*w->border3d.bsize)-2; xsdif=newxs-w->xs; ysdif=newys-w->ys; p=w->objects; while (p!=NULL) { if (p->autoresizex) p->xs+=xsdif; if (p->autoresizey) p->ys+=ysdif; p=p->next; } w->x=newx; w->y=newy; w->xs=newxs; w->ys=newys; check_window(w); }