jwindow.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. #include "video.hpp"
  2. #include "image.hpp"
  3. #include "event.hpp"
  4. #include "filter.hpp"
  5. #include "event.hpp"
  6. #include "jwindow.hpp"
  7. int jw_left=5,jw_right=5,jw_top=15,jw_bottom=5;
  8. int frame_top() { return jw_top; }
  9. int frame_bottom() { return jw_bottom; }
  10. int frame_left() { return jw_left; }
  11. int frame_right() { return jw_right; }
  12. ifield::~ifield() { ; }
  13. void set_frame_size(int x)
  14. {
  15. if (x<1) x=1;
  16. jw_left=x;
  17. jw_right=x;
  18. jw_top=10+x;
  19. jw_bottom=x;
  20. }
  21. // true if a window lies in this area
  22. int window_manager::window_in_area(int x1, int y1, int x2, int y2)
  23. {
  24. for (jwindow *f=first;f;f=f->next)
  25. if (f->x<=x2 && f->y<=y2 && f->x+f->l-1>=x1 && f->y+f->h-1>=y1)
  26. return 1;
  27. return 0;
  28. }
  29. void window_manager::grab_focus(jwindow *j)
  30. { grab=j; }
  31. void window_manager::release_focus()
  32. { grab=NULL; }
  33. void window_manager::close_window(jwindow *j)
  34. {
  35. jwindow *k;
  36. if (grab==j) grab=NULL;
  37. if (state==dragging && j==drag_window) // close the window we were dragging
  38. state=inputing;
  39. if (j==first)
  40. first=first->next;
  41. else
  42. {
  43. for (k=first;k->next!=j;k=k->next)
  44. k->screen->add_dirty(j->x-k->x,j->y-k->y,
  45. j->x+j->l-1-k->x,j->y+j->h-1-k->y);
  46. k->screen->add_dirty(j->x-k->x,j->y-k->y,
  47. j->x+j->l-1-k->x,j->y+j->h-1-k->y);
  48. k->next=j->next;
  49. }
  50. screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
  51. delete j;
  52. }
  53. void window_manager::hide_windows()
  54. {
  55. jwindow *p;
  56. for (p=first;p;p=p->next)
  57. {
  58. if (!p->property.hidden)
  59. {
  60. p->property.hidden=1;
  61. screen->add_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
  62. }
  63. }
  64. }
  65. void window_manager::show_windows()
  66. {
  67. jwindow *p;
  68. for (p=first;p;p=p->next)
  69. if (p->property.hidden)
  70. show_window(p);
  71. }
  72. void window_manager::hide_window(jwindow *j)
  73. {
  74. jwindow *k;
  75. if (j==first)
  76. first=first->next;
  77. else
  78. {
  79. for (k=first;k->next!=j;k=k->next)
  80. k->screen->add_dirty(j->x-k->x,j->y-k->y,
  81. j->x+j->l-1-k->x,j->y+j->h-1-k->y);
  82. k->screen->add_dirty(j->x-k->x,j->y-k->y,
  83. j->x+j->l-1-k->x,j->y+j->h-1-k->y);
  84. k->next=j->next;
  85. }
  86. screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
  87. j->property.hidden=1;
  88. }
  89. void window_manager::show_window(jwindow *j)
  90. {
  91. if (j->property.hidden)
  92. {
  93. j->property.hidden=0;
  94. j->screen->add_dirty(0,0,j->l-1,j->h-1);
  95. }
  96. }
  97. void window_manager::get_event(event &ev)
  98. {
  99. jwindow *j;
  100. eh->get_event(ev);
  101. if (ev.type==EV_KEY)
  102. key_state[ev.key]=1;
  103. else if (ev.type==EV_KEYRELEASE)
  104. key_state[ev.key]=0;
  105. if (state==inputing)
  106. {
  107. for (ev.window=NULL,j=first;j;j=j->next)
  108. if (!j->property.hidden && ev.mouse_move.x>=j->x && ev.mouse_move.y>=j->y &&
  109. ev.mouse_move.x<j->x+j->l && ev.mouse_move.y<j->y+j->h)
  110. ev.window=j;
  111. if (!ev.window && grab) ev.window=grab;
  112. if (ev.window)
  113. {
  114. int closew=0,movew=0;
  115. if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1 && ev.window &&
  116. ev.mouse_move.x>=ev.window->x && ev.mouse_move.y>=ev.window->y &&
  117. ev.mouse_move.x<ev.window->x+ev.window->l && ev.mouse_move.y<ev.window->y+ev.window->y1()))
  118. {
  119. if (ev.mouse_move.x-ev.window->x<11) closew=1;
  120. else if (ev.window->property.moveable) movew=1;
  121. } else if (grab)
  122. ev.window=grab;
  123. if (ev.type==EV_KEY && ev.key==JK_ESC)
  124. closew=1;
  125. if (closew)
  126. ev.type=EV_CLOSE_WINDOW;
  127. else if (movew)
  128. {
  129. int red=0;
  130. if (ev.window==first) // see if we need to raise the window
  131. {
  132. first=first->next;
  133. if (first)
  134. red=1;
  135. }
  136. else
  137. {
  138. jwindow *last=first;
  139. for (;last->next!=ev.window;last=last->next);
  140. if (ev.window->next)
  141. red=1;
  142. last->next=ev.window->next;
  143. }
  144. if (!first)
  145. first=ev.window;
  146. else
  147. {
  148. jwindow *last=first;
  149. for (;last->next;last=last->next);
  150. last->next=ev.window;
  151. }
  152. ev.window->next=NULL;
  153. if (red)
  154. {
  155. jwindow *j=ev.window,*p;
  156. /* screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
  157. for (p=first;p!=j;p=p->next)
  158. p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);*/
  159. j->screen->add_dirty(0,0,j->l-1,j->h-1);
  160. flush_screen();
  161. }
  162. state=dragging;
  163. drag_window=ev.window;
  164. drag_mousex=ev.window->x-ev.mouse_move.x;
  165. drag_mousey=ev.window->y-ev.mouse_move.y;
  166. ev.type=EV_SPURIOUS;
  167. } else if (ev.window)
  168. ev.window->inm->handle_event(ev,ev.window,this);
  169. }
  170. } else if (state==dragging)
  171. {
  172. ev.window=drag_window;
  173. if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button==0) // user released the mouse
  174. {
  175. state=inputing;
  176. ev.type=EV_SPURIOUS;
  177. } else if (ev.type==EV_MOUSE_MOVE)
  178. {
  179. move_window(drag_window,ev.mouse_move.x+drag_mousex,ev.mouse_move.y+drag_mousey);
  180. flush_screen();
  181. ev.type=EV_DRAG_WINDOW;
  182. ev.window_position.x=ev.mouse_move.x+drag_mousex;
  183. ev.window_position.y=ev.mouse_move.y+drag_mousey;
  184. }
  185. }
  186. if (ev.type==EV_REDRAW)
  187. {
  188. for (j=first;j;j=j->next)
  189. j->screen->add_dirty(ev.redraw.x1-j->x,ev.redraw.y1-j->y,
  190. ev.redraw.x2-j->x,ev.redraw.y2-j->y);
  191. screen->add_dirty(ev.redraw.x1,ev.redraw.y1,ev.redraw.x2,ev.redraw.y2);
  192. flush_screen();
  193. ev.type=EV_SPURIOUS; // we took care of this one by ourselves.
  194. }
  195. }
  196. void jwindow::resize(int L, int H)
  197. {
  198. screen->change_size(L,H);
  199. l=L; h=H;
  200. }
  201. void window_manager::resize_window(jwindow *j, int l, int h)
  202. {
  203. jwindow *p;
  204. screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
  205. for (p=first;p!=j;p=p->next)
  206. p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);
  207. j->resize(l,h);
  208. if (!frame_suppress)
  209. j->redraw(hi,med,low,frame_font());
  210. }
  211. void window_manager::move_window(jwindow *j, int x, int y)
  212. {
  213. jwindow *p;
  214. screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
  215. for (p=first;p!=j;p=p->next)
  216. p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);
  217. j->x=x;
  218. j->y=y;
  219. j->screen->add_dirty(0,0,j->l-1,j->h-1);
  220. }
  221. window_manager::window_manager(image *Screen, palette *Pal, int Hi,
  222. int Med, int Low, JCFont *Font)
  223. {
  224. screen=Screen; hi=Hi; low=Low; med=Med; first=NULL; pal=Pal; grab=NULL;
  225. bk=pal->find_closest(0,0,0);
  226. state=inputing; fnt=Font; wframe_fnt=Font;
  227. memset(key_state,0,sizeof(key_state));
  228. eh=new event_handler(screen,pal);
  229. frame_suppress=0;
  230. }
  231. jwindow *window_manager::new_window(int x, int y, int l, int h, ifield *fields, char *Name)
  232. {
  233. if (x>screen->width()-4) x=screen->width()-25;
  234. if (y>screen->height()-4) y=screen->height()-10;
  235. jwindow *j=new jwindow(x,y,l,h,this,fields,Name),*k;
  236. j->property.hidden=0;
  237. if (!first)
  238. first=j;
  239. else
  240. {
  241. k=first;
  242. while (k->next) k=k->next;
  243. k->next=j;
  244. j->next=NULL;
  245. }
  246. if (!frame_suppress)
  247. j->redraw(hi,med,low,frame_font());
  248. return j;
  249. }
  250. void window_manager::flush_screen()
  251. {
  252. jwindow *p,*q;
  253. int mx,my,but;
  254. image *mouse_pic,*mouse_save;
  255. if (has_mouse())
  256. {
  257. mouse_pic=eh->mouse_sprite()->visual;
  258. mouse_save=eh->mouse_sprite()->save;
  259. mx=eh->mouse->drawx();
  260. my=eh->mouse->drawy();
  261. screen->put_part(mouse_save,0,0,mx,my,mx+mouse_pic->width()-1,my+mouse_pic->height()-1);
  262. mouse_pic->put_image(screen,mx,my,1);
  263. }
  264. for (p=first;p;p=p->next)
  265. if (!p->property.hidden)
  266. screen->delete_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
  267. update_dirty(screen);
  268. if (has_mouse())
  269. mouse_save->put_image(screen,mx,my);
  270. for (p=first;p;p=p->next)
  271. {
  272. if (!p->property.hidden)
  273. {
  274. if (has_mouse())
  275. {
  276. p->screen->put_part(mouse_save,0,0,mx-p->x,my-p->y,
  277. mx-p->x+mouse_pic->width()-1,
  278. my-p->y+mouse_pic->height()-1);
  279. if (has_mouse())
  280. mouse_pic->put_image(p->screen,mx-p->x,my-p->y,1);
  281. }
  282. // screen->delete_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
  283. for (q=p->next;q;q=q->next)
  284. if (!q->property.hidden)
  285. p->screen->delete_dirty(q->x-p->x,
  286. q->y-p->y,
  287. q->x+q->l-1-p->x,
  288. q->y+q->h-1-p->y);
  289. update_dirty(p->screen,p->x,p->y);
  290. if (has_mouse())
  291. mouse_save->put_image(p->screen,mx-p->x,my-p->y,0);
  292. }
  293. }
  294. }
  295. void jwindow::set_moveability(int x)
  296. {
  297. property.moveable=x;
  298. }
  299. jwindow::jwindow(int X, int Y, int L, int H, window_manager *wm, ifield *fields, char *Name)
  300. {
  301. ifield *i;
  302. int x1,y1,x2,y2;
  303. l=0; h=0;
  304. property.moveable=1;
  305. if (fields)
  306. for (i=fields;i;i=i->next)
  307. {
  308. i->area(x1,y1,x2,y2,wm);
  309. if ((int)y2>(int)h)
  310. h=y2+1;
  311. if ((int)x2>(int)l)
  312. l=x2+1;
  313. }
  314. else { l=2; h=2; }
  315. if (L<=0) { l=l-L; } else l=L+jw_left;
  316. if (H<=0) { h=h-H; } else h=H+jw_top;
  317. if (Y<0) y=yres-h+Y-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM-1; else y=Y;
  318. if (X<0) x=xres-l+X-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT-1; else x=X;
  319. backg=wm->medium_color();
  320. l+=WINDOW_FRAME_RIGHT; h+=WINDOW_FRAME_BOTTOM;
  321. // if (!fields) { l+=WINDOW_FRAME_LEFT; h+=WINDOW_FRAME_TOP; }
  322. if (l<18) l=18;
  323. if (h<12) h=12;
  324. screen=new image(l,h,NULL,2);
  325. l=screen->width();
  326. h=screen->height();
  327. screen->clear(backg);
  328. next=NULL;
  329. inm=new input_manager(screen,wm,fields);
  330. if (Name==NULL)
  331. name=strcpy((char *)jmalloc(strlen(" ")+1,"jwindow::window name")," ");
  332. else
  333. name=strcpy((char *)jmalloc(strlen(Name)+1,"jwindow::window name"),Name);
  334. }
  335. void jwindow::local_close() { ; }
  336. void jwindow::redraw(int hi, int med, int low, JCFont *fnt)
  337. {
  338. if (jw_right>=3)
  339. screen->rectangle(0,0,l-3,h-3,low);
  340. if (jw_right>=2)
  341. screen->rectangle(1,1,l-2,h-2,med);
  342. if (jw_right>=1)
  343. screen->rectangle(2,2,l-1,h-1,hi);
  344. screen->wiget_bar(0,0,l-1,8,hi,med,low);
  345. screen->line(1,1,l-2,1,low);
  346. screen->line(1,3,l-2,3,low);
  347. screen->line(1,5,l-2,5,low);
  348. screen->line(1,7,l-2,7,low);
  349. screen->wiget_bar(4,3,10,5,hi,med,low);
  350. screen->rectangle(3,2,11,6,0);
  351. screen->line(0,8,l-1,8,0);
  352. if (jw_right>=1)
  353. screen->wiget_bar(0,9,l-1,h-1,hi,med,low);
  354. screen->wiget_bar(0,9,l-1,h-1,hi,med,low);
  355. if (jw_right>=2)
  356. screen->wiget_bar(4,13,l-jw_right,h-jw_right,low,med,hi);
  357. if (name && name[0] && (name[0]!=' ' || name[1]))
  358. {
  359. short cx1,cy1,cx2,cy2;
  360. screen->get_clip(cx1,cy1,cx2,cy2);
  361. screen->set_clip(14,1,l-2,WINDOW_FRAME_TOP-4);
  362. screen->bar(14,1,14+fnt->width()*strlen(name),15-8,med);
  363. fnt->put_string(screen,14,1,name,low);
  364. screen->set_clip(cx1,cy1,cx2,cy2);
  365. }
  366. screen->bar(x1(),y1(),x2(),y2(),backg);
  367. inm->redraw();
  368. }
  369. ifield *input_manager::unlink(int id) // unlinks ID from fields list and return the pointer to it
  370. {
  371. for (ifield *i=first,*last;i;i=i->next)
  372. {
  373. if (i->id==id)
  374. {
  375. if (i==first)
  376. first=first->next;
  377. else
  378. last->next=i->next;
  379. if (active==i)
  380. active=first;
  381. return i;
  382. }
  383. ifield *x=i->unlink(id);
  384. if (x) return x;
  385. last=i;
  386. }
  387. return NULL; // no such id
  388. }
  389. input_manager::~input_manager()
  390. { ifield *i;
  391. while (first)
  392. { i=first;
  393. first=first->next;
  394. delete i;
  395. }
  396. }
  397. void input_manager::clear_current()
  398. {
  399. if (active)
  400. active->draw(0,screen,wm);
  401. active=NULL;
  402. }
  403. void input_manager::handle_event(event &ev, jwindow *j, window_manager *wm)
  404. {
  405. ifield *i,*in_area=NULL;
  406. int x1,y1,x2,y2;
  407. if (j)
  408. {
  409. ev.mouse_move.x-=j->x;
  410. ev.mouse_move.y-=j->y;
  411. cur=j;
  412. }
  413. if (!grab)
  414. {
  415. if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1) || ev.type==EV_MOUSE_MOVE)
  416. {
  417. for (i=first;i;i=i->next)
  418. {
  419. i->area(x1,y1,x2,y2,wm);
  420. if (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
  421. ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2)
  422. in_area=i;
  423. }
  424. if (in_area!=active && (no_selections_allowed || (in_area && in_area->selectable())))
  425. {
  426. if (active)
  427. active->draw(0,screen,wm);
  428. active=in_area;
  429. if (active)
  430. active->draw(1,screen,wm);
  431. }
  432. }
  433. if (ev.type==EV_KEY && ev.key==JK_TAB && active)
  434. {
  435. active->draw(0,screen,wm);
  436. do
  437. {
  438. active=active->next;
  439. if (!active) active=first;
  440. } while (active && !active->selectable());
  441. active->draw(1,screen,wm);
  442. }
  443. } else active=grab;
  444. if (active)
  445. {
  446. if (ev.type!=EV_MOUSE_MOVE && ev.type!=EV_MOUSE_BUTTON)
  447. active->handle_event(ev,screen,wm,this);
  448. else
  449. {
  450. active->area(x1,y1,x2,y2,wm);
  451. if (grab || (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
  452. ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2))
  453. {
  454. if (j)
  455. active->handle_event(ev,screen,wm,j->inm);
  456. else active->handle_event(ev,screen,wm,this);
  457. }
  458. }
  459. }
  460. if (j)
  461. {
  462. ev.mouse_move.x+=j->x;
  463. ev.mouse_move.y+=j->y;
  464. }
  465. }
  466. void input_manager::allow_no_selections()
  467. {
  468. no_selections_allowed=1;
  469. }
  470. void input_manager::redraw()
  471. {
  472. ifield *i;
  473. for (i=first;i;i=i->next)
  474. i->draw_first(screen,wm);
  475. if (active)
  476. active->draw(1,screen,wm);
  477. }
  478. input_manager::input_manager(image *Screen, window_manager *WM, ifield *First)
  479. {
  480. no_selections_allowed=0;
  481. cur=NULL;
  482. grab=NULL;
  483. screen=Screen;
  484. wm=WM;
  485. active=first=First;
  486. while (active && !active->selectable()) active=active->next;
  487. redraw();
  488. }
  489. void input_manager::grab_focus(ifield *i)
  490. { grab=i;
  491. if (cur)
  492. wm->grab_focus(cur);
  493. }
  494. void input_manager::release_focus()
  495. { grab=NULL;
  496. if (cur)
  497. wm->release_focus();
  498. }
  499. void input_manager::remap(filter *f)
  500. {
  501. for (ifield *i=first;i;i=i->next)
  502. i->remap(f);
  503. redraw();
  504. }
  505. void input_manager::add(ifield *i)
  506. { ifield *f=first;
  507. if (i->selectable())
  508. {
  509. if (!f)
  510. first=i;
  511. else
  512. {
  513. while (f->next) f=f->next;
  514. f->next=i;
  515. }
  516. }
  517. }
  518. ifield *input_manager::get(int id)
  519. {
  520. ifield *f;
  521. for (f=first;f;f=f->next)
  522. {
  523. ifield *ret=f->find(id);
  524. if (ret) return ret;
  525. }
  526. return NULL;
  527. }