tabsheet.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #include "precomp.h"
  2. #include "tabsheet.h"
  3. #include "buttwnd.h"
  4. #include "buttbar.h"
  5. #include "tabsheetbar.h"
  6. #include <bfc/wasabi_std.h>
  7. #include <api/wnd/notifmsg.h>
  8. #include <api/script/objects/c_script/c_text.h>
  9. #include <api/script/objects/c_script/c_group.h>
  10. #include <api/wnd/PaintCanvas.h>
  11. TabSheet::TabSheet(int bbtype) {
  12. leftscroll = rightscroll = NULL;
  13. background = NULL;
  14. tabrowmargin = 0;
  15. active = NULL;
  16. type = bbtype;
  17. bb = NULL;
  18. tsb = NULL;
  19. content_margin_top = content_margin_right = content_margin_left = content_margin_bottom = 0;
  20. contentwnd = NULL;
  21. if (bbtype == TABSHEET_GROUPS) {
  22. tsb = new TabSheetBar();
  23. tsb->setParent(this);
  24. } else { // schweitn rulz
  25. bb = new ButtBar((bbtype == -1) ? ButtBar::NORMAL : bbtype);
  26. bb->setParent(this);
  27. if (bbtype == TABSHEET_NOTABS)
  28. bb->setStartHidden(1);
  29. }
  30. }
  31. TabSheet::~TabSheet() {
  32. delete bb; // kills tabs and child wnds
  33. delete tsb;
  34. delete leftscroll;
  35. delete rightscroll;
  36. delete background;
  37. delete contentwnd;
  38. }
  39. void TabSheet::setButtonType(int _type) {
  40. type = _type;
  41. if (contentwnd != NULL) {
  42. if (type == ButtBar::STACK)
  43. contentwnd->setContent(L"wasabi.tabsheet.content.noborder");
  44. else if (type != TABSHEET_NOTABS)
  45. contentwnd->setContent(L"wasabi.tabsheet.content");
  46. else
  47. contentwnd->setContent(NULL);
  48. }
  49. if (_type == TABSHEET_GROUPS && bb != NULL) {
  50. PtrList<BaseWnd> l;
  51. foreach(tabs)
  52. l.addItem(tabs.getfor()->getBaseWnd());
  53. tabs.getfor()->setNoDeleteLinked(1);
  54. endfor;
  55. delete bb; bb = NULL;
  56. tabs.removeAll();
  57. tsb = new TabSheetBar();
  58. tsb->setParent(this);
  59. if (isInited())
  60. tsb->init(this);
  61. foreach(l)
  62. addChild(l.enumItem(foreach_index));
  63. endfor;
  64. } else if (_type != TABSHEET_GROUPS && tsb != NULL) {
  65. PtrList<BaseWnd> l;
  66. foreach(tabs)
  67. l.addItem(tabs.getfor()->getBaseWnd());
  68. tabs.getfor()->setNoDeleteLinked(1);
  69. endfor;
  70. delete tsb; tsb = NULL;
  71. tabs.removeAll();
  72. bb = new ButtBar((type == -1) ? ButtBar::NORMAL : type);
  73. bb->setParent(this);
  74. if (type == TABSHEET_NOTABS)
  75. bb->setStartHidden(1);
  76. if (isInited())
  77. bb->init(this);
  78. foreach(l)
  79. addChild(l.enumItem(foreach_index));
  80. endfor;
  81. }
  82. if (bb != NULL) bb->setResizeMode(type);
  83. }
  84. void TabSheet::killChildren() {
  85. if (bb) {
  86. delete bb; // kills tabs and child wnds
  87. bb = new ButtBar((type == -1) ? ButtBar::NORMAL : type);
  88. bb->setParent(this);
  89. if (type == TABSHEET_NOTABS)
  90. bb->setStartHidden(1);
  91. bb->init(this);
  92. }
  93. if (tsb) {
  94. delete tsb; // kills tabs and child wnds
  95. tsb = new TabSheetBar;
  96. tsb->setParent(this);
  97. tsb->init(this);
  98. }
  99. // mig: if you don't do this, you crash changing tabsheets at runtime.
  100. tabs.removeAll();
  101. active = NULL;
  102. }
  103. int TabSheet::onInit() {
  104. TABSHEET_PARENT::onInit();
  105. contentwnd = new GuiObjectWnd;
  106. if (type == ButtBar::STACK)
  107. contentwnd->setContent(L"wasabi.tabsheet.content.noborder");
  108. else if (type != TABSHEET_NOTABS)
  109. contentwnd->setContent(L"wasabi.tabsheet.content");
  110. else
  111. contentwnd->setContent(NULL);
  112. contentwnd->setParent(this);
  113. contentwnd->init(this);
  114. rootwndholder_setRootWnd(contentwnd);
  115. if (leftscroll != NULL) {
  116. leftscroll->init(this);
  117. leftscroll->setParent(this);
  118. }
  119. if (rightscroll != NULL) {
  120. rightscroll->init(this);
  121. rightscroll->setParent(this);
  122. }
  123. // init the windows
  124. foreach(tabs)
  125. if (foreach_index != 0) tabs.getfor()->getBaseWnd()->setStartHidden(TRUE);
  126. tabs.getfor()->getBaseWnd()->init(this);
  127. endfor
  128. if (bb) {
  129. bb->setParent(this);
  130. if (type == TABSHEET_NOTABS)
  131. bb->setStartHidden(1);
  132. bb->init(this); // inits the tabs
  133. }
  134. if (tsb) {
  135. tsb->setParent(this);
  136. tsb->init(this); // inits the tabs
  137. }
  138. if (tabs.getNumItems() > 0) {
  139. active = tabs[0]->getBaseWnd();
  140. //tabs[0]->setHilite(TRUE); // FG: FIX!
  141. }
  142. if (isPostOnInit())
  143. onResize();
  144. return 1;
  145. }
  146. void TabSheet::getClientRect(RECT *r) {
  147. TABSHEET_PARENT::getClientRect(r);
  148. if (bb) {
  149. if (type != TABSHEET_NOTABS)
  150. r->top += bb->getHeight();
  151. } else
  152. r->top += tsb->getHeight();
  153. r->left += content_margin_left;
  154. r->top += content_margin_top;
  155. r->right -= content_margin_right;
  156. r->bottom -= content_margin_bottom;
  157. }
  158. #ifdef WASABI_COMPILE_IMGLDR
  159. void TabSheet::setBackgroundBmp(const wchar_t *name)
  160. {
  161. if (background) delete background;
  162. background = NULL;
  163. if (name && *name)
  164. background = new SkinBitmap(name);
  165. }
  166. #endif
  167. SkinBitmap *TabSheet::getBackgroundBitmap() {
  168. return background;
  169. }
  170. int TabSheet::onPaint(Canvas *canvas) {
  171. PaintBltCanvas paintcanvas;
  172. if (canvas == NULL) {
  173. if (!paintcanvas.beginPaintNC(this)) return 0;
  174. canvas = &paintcanvas;
  175. }
  176. TABSHEET_PARENT::onPaint(canvas);
  177. RECT r;
  178. TABSHEET_PARENT::getClientRect(&r);
  179. if (bb) {
  180. if (type != TABSHEET_NOTABS)
  181. r.bottom = r.top + bb->getHeight();
  182. }
  183. else if (tsb)
  184. r.bottom = r.top + tsb->getHeight();
  185. RECT br = r;
  186. if (leftscroll) br.left += leftscroll->getWidth();
  187. if (rightscroll) br.right -= rightscroll->getWidth();
  188. if (br.right <= br.left) return 1;
  189. if (background != NULL) {
  190. #if 0
  191. int i, x = tilex;
  192. for (i = 0; ; i++) {
  193. tile->stretch(canvas, x, 0, tile->getWidth(), tabrowheight);
  194. x += tile->getWidth();
  195. if (x >= r.right) break;
  196. }
  197. #else
  198. #if 0
  199. if (background->getAlpha()) api->skin_renderBaseTexture(canvas, br);
  200. background->stretchToRectAlpha(canvas, &br);
  201. #else
  202. background->stretchToRect(canvas, &br);
  203. #endif
  204. #endif
  205. } else {
  206. #if 0
  207. r.top = 0;
  208. r.bottom = tabrowheight;
  209. r.left = tilex;
  210. r.right = tilex + tilew;
  211. canvas->fillRect(&r, RGB(64, 64, 64));
  212. #else
  213. // api->skin_renderBaseTexture(canvas, r);
  214. #endif
  215. }
  216. return 1;
  217. }
  218. void TabSheet::setTabRowMargin(int newmargin) {
  219. ASSERT(newmargin >= 0);
  220. tabrowmargin = newmargin;
  221. onResize();
  222. }
  223. int TabSheet::addChild(BaseWnd *newchild, const wchar_t *tip) {
  224. ASSERT(newchild != NULL);
  225. int first=0;
  226. if (tabs.getNumItems() == 0) first = 1;
  227. if (isInited() && !newchild->isInited()) {
  228. if (!first) newchild->setStartHidden(TRUE);
  229. ifc_window *holder = this;
  230. if (contentwnd != NULL) {
  231. if (contentwnd->getContentRootWnd() != NULL) {
  232. GuiObject *o = contentwnd->getContent()->guiobject_findObject(L"content");
  233. if (o != NULL)
  234. holder = o->guiobject_getRootWnd();
  235. }
  236. }
  237. newchild->setParent(holder);
  238. newchild->init(holder);
  239. }
  240. if (bb)
  241. {
  242. TabButton *tab = new TabButton(newchild, this, tip);
  243. tabs.addItem(tab);
  244. bb->addChild(tab);
  245. }
  246. else if (tsb)
  247. {
  248. GroupTabButton *tab = new GroupTabButton(newchild, this, tip);
  249. tabs.addItem(tab);
  250. tsb->addChild(tab);
  251. }
  252. if (isInited()) {
  253. if (first) {
  254. activateChild(newchild);
  255. }
  256. }
  257. if (isPostOnInit()) onResize();
  258. return tabs.getNumItems()-1;
  259. }
  260. void TabSheet::activateChild(BaseWnd *newactive) {
  261. BaseWnd *prevactive = active;
  262. if (newactive == NULL) newactive = active;
  263. if (prevactive == newactive) return; // not a switch
  264. #if 0
  265. RECT r = clientRect();
  266. int w = r.right - r.left + 1;
  267. int h = r.bottom - r.top + 1;
  268. #endif
  269. int prevpos=-1, nextpos=-1;
  270. for (int i = 0; i < tabs.getNumItems(); i++) {
  271. if (prevactive == tabs[i]->getBaseWnd()) prevpos = i;
  272. if (newactive == tabs[i]->getBaseWnd()) nextpos = i;
  273. }
  274. if (prevpos != -1) tabs[prevpos]->btn_setHilite(FALSE);
  275. if (nextpos < tabs.getNumItems()) tabs[nextpos]->btn_setHilite(TRUE);
  276. #if 0
  277. // reveal tha new winder
  278. if (newactive!= NULL) newactive->setVisible(TRUE);
  279. enable(FALSE);
  280. if (prevactive!= NULL) prevactive->enable(FALSE);
  281. if (newactive!= NULL) newactive->enable(FALSE);
  282. #define STEPS 6
  283. // find which window is now active
  284. for (int c = 0; c < STEPS; c++) {
  285. int x;
  286. if (prevpos > nextpos) x = (w * c) / STEPS; // right to left
  287. else x = (w * (STEPS - c)) / STEPS; // left to right
  288. int y = r.top;
  289. if (prevpos > nextpos) {
  290. if (newactive!= NULL) newactive->move(x - w, y);
  291. if (prevactive!= NULL) prevactive->move(x, y);
  292. } else {
  293. if (newactive!= NULL) newactive->move(x, y);
  294. if (prevactive!= NULL) prevactive->move(x - w, y);
  295. }
  296. if (newactive!= NULL) newactive->repaint();
  297. if (prevactive!= NULL) prevactive->repaint();
  298. Sleep(15);
  299. }
  300. #endif
  301. if (newactive!= NULL) newactive->setVisible(TRUE);
  302. if (prevactive!= NULL) prevactive->setVisible(FALSE);
  303. #if 0
  304. enable(TRUE);
  305. if (prevactive!= NULL) prevactive->enable(TRUE);
  306. if (newactive!= NULL) newactive->enable(TRUE);
  307. #endif
  308. if (bb && newactive)
  309. bb->setGroupLabel(newactive->getName());
  310. active = newactive;
  311. onSetPage(nextpos);
  312. }
  313. int TabSheet::onResize() {
  314. TABSHEET_PARENT::onResize();
  315. if (!isInited()) return 1;
  316. RECT r = clientRect();
  317. // put buttbar at the top
  318. if (bb) bb->resize(r.left, r.top-bb->getHeight(), r.right-r.left, bb->getHeight()+1);
  319. if (tsb) tsb->resize(r.left, r.top-tsb->getHeight(), r.right-r.left, tsb->getHeight()+1);
  320. // resize content group if it's there
  321. if (contentwnd) {
  322. contentwnd->resize(&r);
  323. // since its holder is not resizing its content, we need to do it ourselves
  324. foreach(tabs)
  325. BaseWnd *c = tabs.getfor()->getBaseWnd();
  326. if (c->getParent() != NULL && c->getParent() != this && c->getParent()->getParent() == contentwnd->getContentRootWnd()) {
  327. RECT r;
  328. c->getParent()->getClientRect(&r);
  329. c->resize(&r);
  330. } else {
  331. // if we're holding it directly, resize it to our rect
  332. c->resize(&r);
  333. }
  334. endfor
  335. }
  336. invalidate();
  337. if (leftscroll)
  338. leftscroll->invalidate();
  339. if (rightscroll)
  340. rightscroll->invalidate();
  341. return 1;
  342. }
  343. BaseWnd *TabSheet::enumChild(int child) {
  344. TabButtonBase *tb = tabs[child];
  345. if (tb == NULL) return NULL;
  346. return tb->getBaseWnd();
  347. }
  348. int TabSheet::getNumChild() {
  349. return tabs.getNumItems();
  350. }
  351. void TabSheet::setCurPage(int page) {
  352. BaseWnd *e = enumChild(page);
  353. if (e != NULL) activateChild(e);
  354. }
  355. TabButtonBase *TabSheet::enumButton(int i) {
  356. if (i < tabs.getNumItems())
  357. return tabs[i];
  358. else
  359. return NULL;
  360. }
  361. int TabSheet::childNotify(ifc_window *child, int msg, intptr_t param1, intptr_t param2) {
  362. if (msg == ChildNotify::NAMECHANGED)
  363. {
  364. foreach(tabs)
  365. ifc_window *w = tabs.getfor()->getBaseWnd();
  366. if (w == child || w == child->getParent()) {
  367. const wchar_t *name = child->getRootWndName();
  368. tabs.getfor()->btn_setText(name && *name ? name : L"[?]");
  369. }
  370. endfor;
  371. }
  372. if (msg == ChildNotify::GROUPRELOAD && child == contentwnd) {
  373. foreach(tabs)
  374. ifc_window *holder = this;
  375. if (contentwnd->getContentRootWnd() != NULL) {
  376. GuiObject *o = contentwnd->getContent()->guiobject_findObject(L"content");
  377. if (o != NULL)
  378. holder = o->guiobject_getRootWnd();
  379. }
  380. tabs.getfor()->getBaseWnd()->reparent(holder);
  381. endfor;
  382. }
  383. return TABSHEET_PARENT::childNotify(child, msg, param1, param2);
  384. }
  385. void TabSheet::setContentMarginLeft(int cm) {
  386. content_margin_left = cm;
  387. if (isInited())
  388. onResize();
  389. }
  390. void TabSheet::setContentMarginTop(int cm) {
  391. content_margin_top = cm;
  392. if (isInited())
  393. onResize();
  394. }
  395. void TabSheet::setContentMarginRight(int cm) {
  396. content_margin_right = cm;
  397. if (isInited())
  398. onResize();
  399. }
  400. void TabSheet::setContentMarginBottom(int cm) {
  401. content_margin_bottom = cm;
  402. if (isInited())
  403. onResize();
  404. }
  405. int TabSheet::onAction(const wchar_t *action, const wchar_t *param, int x, int y, intptr_t p1, intptr_t p2, void *data, size_t datalen, ifc_window *source) {
  406. if (!WCSICMP(action, L"Tabsheet:NextPage")) { nextPage(); return 1; }
  407. if (!WCSICMP(action, L"Tabsheet:PreviousPage")) { previousPage(); return 1; }
  408. return TABSHEET_PARENT::onAction(action, param, x, y, p1, p2, data, datalen, source);
  409. }
  410. // TabButton
  411. TabButtonBase::TabButtonBase(BaseWnd *linkwnd, TabSheet *par, const wchar_t *tip)
  412. : linked(linkwnd), parent(par) {
  413. nodeletelinked = 0;
  414. ASSERT(linked != NULL);
  415. }
  416. TabButtonBase::~TabButtonBase() {
  417. if (!nodeletelinked) delete linked;
  418. }
  419. int TabButton::onInit()
  420. {
  421. TABBUTTON_PARENT::onInit();
  422. setButtonText(linked->getNameSafe(L"[?]"));
  423. return 1;
  424. }
  425. void TabButton::onLeftPush(int x, int y) {
  426. ASSERT(parent != NULL);
  427. ASSERT(linked != NULL);
  428. parent->activateChild(linked);
  429. }
  430. void TabButton::btn_setHilite(int tf) {
  431. setHilite(tf);
  432. }
  433. void TabButton::btn_setText(const wchar_t *text)
  434. {
  435. setButtonText(text);
  436. }
  437. // GroupTabButton
  438. void GroupTabButton::grouptoggle_onLeftPush() {
  439. GROUPTABBUTTON_PARENT::grouptoggle_onLeftPush();
  440. ASSERT(parent != NULL);
  441. ASSERT(linked != NULL);
  442. parent->activateChild(linked);
  443. }
  444. void GroupTabButton::btn_setHilite(int tf) {
  445. setStatus(tf ? STATUS_ON : STATUS_OFF);
  446. }
  447. void GroupTabButton::btn_setText(const wchar_t *text)
  448. {
  449. for (int i=0;i<getNumGroups();i++) {
  450. GuiObject *grp = enumGroups(i)->getContent();
  451. if (grp != NULL) {
  452. GuiObject *o = grp->guiobject_findObject(L"text");
  453. if (o != NULL) {
  454. C_Text txt(o->guiobject_getScriptObject());
  455. txt.setText(text);
  456. }
  457. }
  458. }
  459. }
  460. int GroupTabButton::onInit() {
  461. int rt = GROUPTABBUTTON_PARENT::onInit();
  462. btn_setText(linked->getNameSafe(L"[?]"));
  463. return rt;
  464. }