001 #ifndef UI_HH
002 #define UI_HH "Pressin B"
003 #include "GarbageCollector";
004 #include "Set.HC";
005 #include "Primtives3D";
006 class CUIElem {
007 //x,y are relative to last element
008   F64 x,y,w,h;
009   F64 x2,y2,w2,h2;
010   U0 (*draw_it)(CUIElem *self,CDC *dc);
011   Bool (*event_cb)(CUIElem *who,I64 type,I64 x,I64 y);
012   CI64Set *sub_elems;
013   Bool invisible,no_occupy_space,pad[6];
014   U8 *user_data;
015 };
016 class CUIButton:CUIElem {
017   U8 *text;
018   I64 bg_color,fg_color;
019   I64 border_color;
020   U0 (*cb)(CUIButton *btn);
021 };
022 class CUITree:CUIButton {
023   Bool open;
024 };
025 
026 class CUIBigText:CUIElem {
027   I64 color;
028   U8 *text;
029   F64 scale;
030 };
031 
032 class CUIText:CUIElem {
033   I64 color;
034   U8 *text;
035 
036 };
037 
038 class CUIRoot:CUIElem {
039 };
040 
041 
042 class CUIGrid:CUIElem {
043   I64 rows,cols;
044   I64 active_row,active_col;
045   CI64Set *items;//CUIGridItem
046 //Private,used for draging
047   I64 ms_down_at_x,ms_down_at_y;
048 }
049 class CUIGridItem {
050   I64 row,col;
051   U8 *sprite;
052   I64 ammo;
053   U0 (*cb)(CUIGridItem *);
054   U8 *user_data;
055 //Private
056   I64 x,y;
057   CUIGrid *parent;
058 };
059 CUIGridItem *UIGridItemNew(U8 *icon) {
060   CUIGridItem *item=GCCAlloc(sizeof CUIGridItem);
061   item->sprite=icon;
062   return item;
063 }
064 U0 UIGridItemRemove(CUIGridItem *i) {
065   CUIGrid *parent=i->parent;
066   if(!parent) return;
067   I64SetRem(parent->items,i);
068   i->parent=NULL;
069 }
070 Bool UIGridAddItem(CUIGrid *grid,CUIGridItem *i) {
071   CI64Set *items=grid->items;
072   CUIGridItem *other;
073   I64 cnt=items->cnt,x,y,idx;
074   for(x=0;x!=grid->cols;++x)
075     for(y=0;y!=grid->rows;++y) {
076       for(idx=0;idx!=cnt;++idx) {
077         other=items->body[idx];
078         if(other->row==y&&other->col==x) {
079           goto no;
080         }
081       }
082       i->parent=grid;
083       i->row=y,i->col=x;
084       I64SetAdd(items,i);
085       return TRUE;
086 no:;
087     }
088   return FALSE;
089 }
090 U0 UIGridDraw(CUIGrid *grid,CDC *dc) {
091   I64 x,y;
092   CI64Set *items;
093   CUIGridItem *item;
094   grid->w2=grid->cols*24;
095   grid->h2=grid->rows*24;
096   grid->w=grid->w2;
097   grid->h=grid->h2;
098 
099   dc->color=DKGRAY;
100   GrRect(dc,grid->x2,grid->y2,grid->w2,grid->h2);
101   for(x=0;x!=grid->cols;++x) {
102     for(y=0;y!=grid->rows;++y) {
103       if(grid->active_row==y&&grid->active_col==x) {
104         if(Blink)
105           dc->color=LTRED;
106         else
107           dc->color=LTCYAN;
108       } else
109         dc->color=BLACK;
110       GrRect(dc,grid->x2+x*24+4,grid->y2+y*24+4,16,16);
111     }
112   }
113   items=grid->items;
114   for(x=0;x!=items->cnt;++x) {
115     item=items->body[x];
116     item->parent=grid;
117     item->x=item->col*24;
118     item->y=item->row*24;
119     if(item->sprite)
120       Sprite3(dc,grid->x2+item->x+4,grid->y2+item->y+4,0,item->sprite);
121   }
122 }
123 CUIGridItem *GridItemAtXY(CUIGrid *grid,I64 x,I64 y) {
124   I64 idx;
125   CI64Set *items;
126   CUIGridItem *item;
127   items=grid->items;
128   for(idx=0;idx!=items->cnt;++idx) {
129     item=items->body[idx];
130     if(0<=x-item->x<24)
131       if(0<=y-item->y<24) {
132         return item;
133       }
134   }
135   return NULL;
136 }
137 Bool UIGridInteract(CUIGrid *grid,I64 msg,I64 x,I64 y) {
138   CUIGridItem *item,*item2;
139   if(msg==MSG_MS_L_DOWN) {
140     item=GridItemAtXY(grid,x,y);
141     if(item) {
142       FramePtrAdd("GridDragActive",item);
143       return TRUE;
144     }
145   }
146   if(msg==MSG_MS_L_UP&&(item=FramePtr("GridDragActive"))) {
147     item2=GridItemAtXY(grid,x,y);
148 //Swap items
149     if(item!=item2&&item2) {
150       I64SetRem(item->parent->items,item);
151       I64SetRem(item2->parent->items,item2);
152       SwapI64(&item->parent,&item2->parent);
153       SwapI64(&item->row,&item2->row);
154       SwapI64(&item->col,&item2->col);
155       I64SetAdd(item->parent->items,item);
156       I64SetAdd(item2->parent->items,item2);
157     } else if(item&&!item2) {
158       I64SetRem(item->parent->items,item);
159       item->parent=grid;
160       item->col=x/24;
161       item->row=y/24;
162       I64SetAdd(item->parent->items,item);
163       if(item->cb)
164         (*item->cb)(item);
165     }
166     FramePtrDel("GridDragActive");
167     return TRUE;
168   }
169   return FALSE;
170 } 
171 CUIGrid *UIGridNew(I64 w,I64 h) {
172   CUIGrid *bt=GCCAlloc(sizeof CUIGrid);
173   bt->event_cb=&UIGridInteract;
174   bt->draw_it=&UIGridDraw;
175   bt->sub_elems=I64SetNew;
176   bt->items=I64SetNew;
177   bt->rows=h;
178   bt->cols=w;
179   return bt;  
180 } 
181 U0 TextDrawIt(CUIText *t,CDC *dc) {
182   dc->color=t->color;
183   t->h2=(StrOcc(t->text,'\n')+1)*8;
184   GrPrint(dc,t->x2,t->y2,"%s",t->text);
185 }
186 U0 BigTextDrawIt(CUIBigText *t,CDC *dc) {
187   I64 oflags=dc->flags,ot=dc->transform;
188   CD6 *mesh=PrimitiveText3D(t->text,4,t->scale,t->color);
189   I64 rev[16],winx,winy,winz,ox,oy;
190   dc->flags|=DCF_TRANSFORMATION;
191   dc->transform=&WorldTransform;
192   Mat4x4IdentEqu(rev);
193   Mat4x4RotY(rev,pi);
194   mesh=CD6NewTransform(mesh,rev);
195   Mat4x4IdentEqu(rev);
196   Mat4x4TranslationEqu(rev,t->x2,t->y2,1000.);
197   winz=1.;
198   winy=ms.pos.y-mem_task->pix_top;
199   winx=ms.pos.x-mem_task->pix_left;
200   Mat4x4PointTo(rev,winx,winy,winz);
201   Mat4x4TranslationEqu(rev,0,0,350.);
202 
203   ox=dc->x,oy=dc->y;
204   dc->x=t->x2;
205   dc->y=t->y2;
206   CD6Draw(mesh,0,0,0,dc,rev);
207   dc->x=ox,dc->y=oy;
208   GCFree(mesh);
209   dc->transform=ot;
210   dc->flags=oflags;
211 }
212 CUIBigText *UIBigTextNew(U8 *str,F64 scale=16.) {
213   CUIBigText *bt=GCCAlloc(sizeof CUIBigText);
214   bt->color=YELLOW;
215   bt->scale=scale;
216   bt->text=GCStrNew(str);
217   bt->draw_it=&BigTextDrawIt;
218   bt->sub_elems=I64SetNew;
219   return bt;  
220 } 
221 CUIText *UITextNew(U8 *str) {
222   CUIText *bt=GCCAlloc(sizeof CUIText);
223   bt->color=RED;
224   bt->text=GCStrNew(str);
225   bt->draw_it=&TextDrawIt;
226   bt->sub_elems=I64SetNew;
227   return bt;  
228 } 
229 //Returns height 21
230 F64  DrawSubElems(CUIElem *e,CDC *dc) {
231   F64 x=e->x2,y=e->y2+e->h2;
232   I64 cnt=e->sub_elems->cnt,idx;
233   CUIElem **sub=e->sub_elems->body,*cur;
234   for(idx=0;idx!=cnt;++idx) {
235     cur=sub[idx];
236     if(!cur->invisible) {
237       cur->x2=x+cur->x;
238       cur->y2=y+cur->y;
239       cur->w2=cur->w;
240       cur->h2=cur->h;
241       if(cur->draw_it)
242         (*cur->draw_it)(cur,dc);
243       if(!cur->no_occupy_space)
244         y+=cur->h2;
245     }
246   }  
247   return y-e->y2;
248 }
249 
250 
251 U0 ButtonDrawIt(CUIButton *bt,CDC *dc) {
252   dc->color=bt->bg_color;
253   GrRect(dc,bt->x2,bt->y2,bt->w2,bt->h2);
254   dc->color=bt->border_color;
255   GrBorder(dc,bt->x2+4,bt->y2+4,bt->x2+bt->w2-8,bt->y2+bt->h2-8);
256   dc->color=bt->fg_color;
257   GrPutS(dc,bt->x2+8,bt->y2+bt->h2/2.-4,bt->text);
258 }
259 
260 U0 TreeDrawIt(CUITree *tree,CDC *dc) {
261   I64 cnt=tree->sub_elems->cnt,idx;
262   CUIElem **sub=tree->sub_elems->body;
263   U8 *tmp=tree->text;
264   if(tree->open)
265     tree->text=MStrPrint("+] %s",tmp);
266   else
267     tree->text=MStrPrint("-] %s",tmp);
268   ButtonDrawIt(tree,dc);
269   Free(tree->text);
270   tree->text=tmp;
271 
272   if(tree->open) {
273     for(idx=0;idx!=cnt;++idx) {
274        sub[idx]->invisible=FALSE;
275     }
276     tree->x2+=32.;
277     tree->h2=DrawSubElems(tree,dc);
278     tree->x2-=32.;
279   } else {
280     for(idx=0;idx!=cnt;++idx) {
281        sub[idx]->invisible=TRUE;
282     }
283     tree->h2=tree->h;
284   }
285 }
286 
287 Bool ButtonInteract(CUIButton *bttn,I64 msg,I64 x,I64 y) {
288   if(msg==MSG_MS_L_DOWN) {
289     if(bttn->cb) {
290       (*bttn->cb)(bttn);
291     }
292     return TRUE;
293   }
294   return FALSE;
295 }
296 
297 CUIButton *UIButtonNew(U8 *label,F64 w=100,F64 h=32) {
298   CUIButton *btn=GCCAlloc(sizeof CUIButton);
299   btn->border_color=WHITE;
300   btn->bg_color=BLACK;
301   btn->fg_color=WHITE;
302   btn->w=w,btn->h=h;
303   btn->text=GCStrNew(label);
304   btn->sub_elems=I64SetNew;
305   btn->draw_it=&ButtonDrawIt;
306   btn->event_cb=&ButtonInteract;
307   return btn;
308 }
309 
310 Bool MouseInElem(CUIElem *e,I64 x,I64 y) {
311   if(e->x2<=x<e->x2+e->w) {
312     if(e->y2<=y<e->y2+e->h) {
313       return TRUE;
314      }
315   }
316   return FALSE;
317 }
318 
319 Bool TreeInteract(CUITree *tree,I64 msg,I64 x,I64 y) {
320   if(msg==MSG_MS_L_DOWN) {
321      tree->open^=TRUE;
322     return TRUE;
323   }
324   return FALSE;
325 }
326 CUIButton *UITreeNew(U8 *label,F64 w=100,F64 h=32) {
327   CUIButton *btn=GCCAlloc(sizeof CUITree);
328   btn->w=w,btn->h=h;
329   btn->text=GCStrNew(label);
330   btn->sub_elems=I64SetNew;
331   btn->event_cb=&TreeInteract;
332   btn->border_color=PURPLE;
333   btn->bg_color=BLACK;
334   btn->fg_color=PURPLE;
335   btn->draw_it=&TreeDrawIt;
336   return btn;
337 }
338 
339 
340 CUIRoot *UIRootNew() {
341   CUIButton *root=GCCAlloc(sizeof CUIRoot);
342   root->w=GR_WIDTH,root->h=GR_HEIGHT;
343   root->sub_elems=I64SetNew;
344   return root;
345 }
346 
347 U0 UIElemAdd(CUIElem *to,CUIElem *who) {
348   I64SetAdd(to->sub_elems,who);
349 }
350 
351 
352 CUIRoot *ui_root=UIRootNew;
353 U0 DrawUI(CTask *t,CDC *dc) {
354   DrawSubElems(ui_root,dc);
355 }
356 Bool UIMsg(CUIElem *e,I64 t,I64 x,I64 y,Bool root=TRUE) {
357   I64 cnt=e->sub_elems->cnt,idx;
358   CUIElem **sub=e->sub_elems->body,*cur;
359   Bool ret=FALSE;
360   for(idx=0;idx!=cnt;++idx) {
361     cur=sub[idx];
362     if(!cur->invisible) {
363       switch(t) {
364         case MSG_MS_L_UP:
365         case MSG_MS_MOVE:
366         case MSG_MS_L_DOWN:
367         case MSG_MS_R_UP:
368         case MSG_MS_R_DOWN:
369         case MSG_MS_L_D_UP:
370         case MSG_MS_R_D_UP:
371         case MSG_MS_L_D_DOWN:
372         case MSG_MS_R_D_DOWN:
373           if(ret=UIMsg(cur,t,x,y,FALSE))
374             goto en;
375           break;
376         default:
377           if(ret=UIMsg(cur,t,x,y,FALSE))
378             goto en;
379       }
380     }
381   } 
382   if(e->event_cb) {
383     switch(t) {
384       case MSG_MS_L_UP:
385       case MSG_MS_MOVE:
386       case MSG_MS_L_DOWN:
387       case MSG_MS_R_UP:
388       case MSG_MS_R_DOWN:
389       case MSG_MS_L_D_UP:
390       case MSG_MS_R_D_UP:
391       case MSG_MS_L_D_DOWN:
392       case MSG_MS_R_D_DOWN:
393         if(MouseInElem(e,x,y))
394           if(ret=(*e->event_cb)(e,t,x-e->x2,y-e->y2))
395             goto en;
396         break;
397       default:
398         if(ret=(*e->event_cb)(e,t,x,y))
399           goto en;
400         break;
401     }
402   }
403 en:
404   if(t==MSG_MS_L_UP)
405     if(root&&!ret&&FramePtr("GridDragActive"))
406       FramePtrDel("GridDragActive");
407   return ret;
408 }
409 
410 #if __CMD_LINE__
411 <1>
//// 412 //// 413 <2>
//// 414 //// 415 416 417 418 419 420 U8 *sprite; 421 U0 BeepPress(CUIButton *b) { 422 Beep; 423 } 424 CUITree *tree=UITreeNew("Asswipe"); 425 CUIButton *btn1=UIButtonNew("tp"); 426 CUIButton *btn2=UIButtonNew("tp2"); 427 CUIBigText *bt=UIBigTextNew("Hello:\n$100",64); 428 CUIGrid *grid=UIGridNew(10,1);; 429 CUIGridItem *gride=UIGridItemNew(<1>); 430 CUIGridItem *gride2=UIGridItemNew(<2>); 431 UIGridAddItem(grid,gride); 432 UIGridAddItem(grid,gride2); 433 grid->x=300; 434 //grid->y=100; 435 bt->x=100; 436 bt->y=200; 437 CUIBigText *bt2=UIBigTextNew("World",64); 438 bt2->x=GR_WIDTH-100; 439 bt2->y=200; 440 CUIText *txt=UITextNew("Anal\nBeads"); 441 UIElemAdd(ui_root,tree); 442 UIElemAdd(ui_root,grid); 443 UIElemAdd(ui_root,bt); 444 UIElemAdd(ui_root,bt2); 445 UIElemAdd(tree,btn1); 446 UIElemAdd(tree,btn2); 447 UIElemAdd(tree,txt); 448 btn2->cb=&BeepPress; 449 Fs->draw_it=&DrawUI; 450 I64 t,x,y; 451 DocClear; 452 while(TRUE) { 453 while(t=ScanMsg(&x,&y)) { 454 UIMsg(ui_root,t,x,y); 455 } 456 Refresh; 457 } 458 #endif 459 #endif