diff options
Diffstat (limited to 'Src/Wasabi/api/wnd/wndclass/tabsheet.cpp')
-rw-r--r-- | Src/Wasabi/api/wnd/wndclass/tabsheet.cpp | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/wndclass/tabsheet.cpp b/Src/Wasabi/api/wnd/wndclass/tabsheet.cpp new file mode 100644 index 00000000..6323fcc2 --- /dev/null +++ b/Src/Wasabi/api/wnd/wndclass/tabsheet.cpp @@ -0,0 +1,544 @@ +#include "precomp.h" +#include "tabsheet.h" +#include "buttwnd.h" +#include "buttbar.h" +#include "tabsheetbar.h" + +#include <bfc/wasabi_std.h> +#include <api/wnd/notifmsg.h> +#include <api/script/objects/c_script/c_text.h> +#include <api/script/objects/c_script/c_group.h> +#include <api/wnd/PaintCanvas.h> + +TabSheet::TabSheet(int bbtype) { + leftscroll = rightscroll = NULL; + background = NULL; + tabrowmargin = 0; + active = NULL; + type = bbtype; + bb = NULL; + tsb = NULL; + content_margin_top = content_margin_right = content_margin_left = content_margin_bottom = 0; + contentwnd = NULL; + + if (bbtype == TABSHEET_GROUPS) { + tsb = new TabSheetBar(); + tsb->setParent(this); + } else { // schweitn rulz + bb = new ButtBar((bbtype == -1) ? ButtBar::NORMAL : bbtype); + bb->setParent(this); + if (bbtype == TABSHEET_NOTABS) + bb->setStartHidden(1); + } +} + +TabSheet::~TabSheet() { + delete bb; // kills tabs and child wnds + delete tsb; + delete leftscroll; + delete rightscroll; + delete background; + delete contentwnd; +} + +void TabSheet::setButtonType(int _type) { + type = _type; + if (contentwnd != NULL) { + if (type == ButtBar::STACK) + contentwnd->setContent(L"wasabi.tabsheet.content.noborder"); + else if (type != TABSHEET_NOTABS) + contentwnd->setContent(L"wasabi.tabsheet.content"); + else + contentwnd->setContent(NULL); + } + if (_type == TABSHEET_GROUPS && bb != NULL) { + PtrList<BaseWnd> l; + foreach(tabs) + l.addItem(tabs.getfor()->getBaseWnd()); + tabs.getfor()->setNoDeleteLinked(1); + endfor; + delete bb; bb = NULL; + tabs.removeAll(); + tsb = new TabSheetBar(); + tsb->setParent(this); + if (isInited()) + tsb->init(this); + foreach(l) + addChild(l.enumItem(foreach_index)); + endfor; + } else if (_type != TABSHEET_GROUPS && tsb != NULL) { + PtrList<BaseWnd> l; + foreach(tabs) + l.addItem(tabs.getfor()->getBaseWnd()); + tabs.getfor()->setNoDeleteLinked(1); + endfor; + delete tsb; tsb = NULL; + tabs.removeAll(); + bb = new ButtBar((type == -1) ? ButtBar::NORMAL : type); + bb->setParent(this); + if (type == TABSHEET_NOTABS) + bb->setStartHidden(1); + if (isInited()) + bb->init(this); + foreach(l) + addChild(l.enumItem(foreach_index)); + endfor; + } + if (bb != NULL) bb->setResizeMode(type); +} + +void TabSheet::killChildren() { + if (bb) { + delete bb; // kills tabs and child wnds + bb = new ButtBar((type == -1) ? ButtBar::NORMAL : type); + bb->setParent(this); + if (type == TABSHEET_NOTABS) + bb->setStartHidden(1); + bb->init(this); + } + if (tsb) { + delete tsb; // kills tabs and child wnds + tsb = new TabSheetBar; + tsb->setParent(this); + tsb->init(this); + } + + // mig: if you don't do this, you crash changing tabsheets at runtime. + tabs.removeAll(); + active = NULL; +} + +int TabSheet::onInit() { + TABSHEET_PARENT::onInit(); + + contentwnd = new GuiObjectWnd; + if (type == ButtBar::STACK) + contentwnd->setContent(L"wasabi.tabsheet.content.noborder"); + else if (type != TABSHEET_NOTABS) + contentwnd->setContent(L"wasabi.tabsheet.content"); + else + contentwnd->setContent(NULL); + contentwnd->setParent(this); + contentwnd->init(this); + rootwndholder_setRootWnd(contentwnd); + + if (leftscroll != NULL) { + leftscroll->init(this); + leftscroll->setParent(this); + } + if (rightscroll != NULL) { + rightscroll->init(this); + rightscroll->setParent(this); + } + + // init the windows + foreach(tabs) + if (foreach_index != 0) tabs.getfor()->getBaseWnd()->setStartHidden(TRUE); + tabs.getfor()->getBaseWnd()->init(this); + endfor + + if (bb) { + bb->setParent(this); + if (type == TABSHEET_NOTABS) + bb->setStartHidden(1); + bb->init(this); // inits the tabs + } + if (tsb) { + tsb->setParent(this); + tsb->init(this); // inits the tabs + } + + if (tabs.getNumItems() > 0) { + active = tabs[0]->getBaseWnd(); + //tabs[0]->setHilite(TRUE); // FG: FIX! + } + + if (isPostOnInit()) + onResize(); + + return 1; +} + +void TabSheet::getClientRect(RECT *r) { + TABSHEET_PARENT::getClientRect(r); + if (bb) { + if (type != TABSHEET_NOTABS) + r->top += bb->getHeight(); + } else + r->top += tsb->getHeight(); + + r->left += content_margin_left; + r->top += content_margin_top; + r->right -= content_margin_right; + r->bottom -= content_margin_bottom; +} + +#ifdef WASABI_COMPILE_IMGLDR +void TabSheet::setBackgroundBmp(const wchar_t *name) +{ + if (background) delete background; + background = NULL; + if (name && *name) + background = new SkinBitmap(name); +} +#endif + +SkinBitmap *TabSheet::getBackgroundBitmap() { + return background; +} + +int TabSheet::onPaint(Canvas *canvas) { + + PaintBltCanvas paintcanvas; + if (canvas == NULL) { + if (!paintcanvas.beginPaintNC(this)) return 0; + canvas = &paintcanvas; + } + TABSHEET_PARENT::onPaint(canvas); + + RECT r; + TABSHEET_PARENT::getClientRect(&r); + + if (bb) { + if (type != TABSHEET_NOTABS) + r.bottom = r.top + bb->getHeight(); + } + else if (tsb) + r.bottom = r.top + tsb->getHeight(); + + RECT br = r; + if (leftscroll) br.left += leftscroll->getWidth(); + if (rightscroll) br.right -= rightscroll->getWidth(); + + if (br.right <= br.left) return 1; + + if (background != NULL) { +#if 0 + int i, x = tilex; + for (i = 0; ; i++) { + tile->stretch(canvas, x, 0, tile->getWidth(), tabrowheight); + x += tile->getWidth(); + if (x >= r.right) break; + } +#else +#if 0 + if (background->getAlpha()) api->skin_renderBaseTexture(canvas, br); + background->stretchToRectAlpha(canvas, &br); +#else + background->stretchToRect(canvas, &br); +#endif +#endif + } else { +#if 0 + r.top = 0; + r.bottom = tabrowheight; + r.left = tilex; + r.right = tilex + tilew; + canvas->fillRect(&r, RGB(64, 64, 64)); +#else +// api->skin_renderBaseTexture(canvas, r); +#endif + } + + return 1; +} + +void TabSheet::setTabRowMargin(int newmargin) { + ASSERT(newmargin >= 0); + tabrowmargin = newmargin; + onResize(); +} + +int TabSheet::addChild(BaseWnd *newchild, const wchar_t *tip) { + + ASSERT(newchild != NULL); + + int first=0; + if (tabs.getNumItems() == 0) first = 1; + + if (isInited() && !newchild->isInited()) { + if (!first) newchild->setStartHidden(TRUE); + + ifc_window *holder = this; + if (contentwnd != NULL) { + if (contentwnd->getContentRootWnd() != NULL) { + GuiObject *o = contentwnd->getContent()->guiobject_findObject(L"content"); + if (o != NULL) + holder = o->guiobject_getRootWnd(); + } + } + newchild->setParent(holder); + newchild->init(holder); + } + + if (bb) + { + TabButton *tab = new TabButton(newchild, this, tip); + tabs.addItem(tab); + bb->addChild(tab); + } + else if (tsb) + { + GroupTabButton *tab = new GroupTabButton(newchild, this, tip); + tabs.addItem(tab); + tsb->addChild(tab); + } + if (isInited()) { + if (first) { + activateChild(newchild); + } + } + if (isPostOnInit()) onResize(); + return tabs.getNumItems()-1; +} + +void TabSheet::activateChild(BaseWnd *newactive) { + BaseWnd *prevactive = active; + if (newactive == NULL) newactive = active; + + if (prevactive == newactive) return; // not a switch + +#if 0 + RECT r = clientRect(); + + int w = r.right - r.left + 1; + int h = r.bottom - r.top + 1; +#endif + + int prevpos=-1, nextpos=-1; + + for (int i = 0; i < tabs.getNumItems(); i++) { + if (prevactive == tabs[i]->getBaseWnd()) prevpos = i; + if (newactive == tabs[i]->getBaseWnd()) nextpos = i; + } + + if (prevpos != -1) tabs[prevpos]->btn_setHilite(FALSE); + if (nextpos < tabs.getNumItems()) tabs[nextpos]->btn_setHilite(TRUE); + +#if 0 + // reveal tha new winder + if (newactive!= NULL) newactive->setVisible(TRUE); + + enable(FALSE); + if (prevactive!= NULL) prevactive->enable(FALSE); + if (newactive!= NULL) newactive->enable(FALSE); + +#define STEPS 6 + + // find which window is now active + for (int c = 0; c < STEPS; c++) { + int x; + if (prevpos > nextpos) x = (w * c) / STEPS; // right to left + else x = (w * (STEPS - c)) / STEPS; // left to right + int y = r.top; + if (prevpos > nextpos) { + if (newactive!= NULL) newactive->move(x - w, y); + if (prevactive!= NULL) prevactive->move(x, y); + } else { + if (newactive!= NULL) newactive->move(x, y); + if (prevactive!= NULL) prevactive->move(x - w, y); + } + if (newactive!= NULL) newactive->repaint(); + if (prevactive!= NULL) prevactive->repaint(); + Sleep(15); + } +#endif + + if (newactive!= NULL) newactive->setVisible(TRUE); + + if (prevactive!= NULL) prevactive->setVisible(FALSE); + +#if 0 + enable(TRUE); + if (prevactive!= NULL) prevactive->enable(TRUE); + if (newactive!= NULL) newactive->enable(TRUE); +#endif + + if (bb && newactive) + bb->setGroupLabel(newactive->getName()); + active = newactive; + onSetPage(nextpos); +} + +int TabSheet::onResize() { + TABSHEET_PARENT::onResize(); + + if (!isInited()) return 1; + + RECT r = clientRect(); + + // put buttbar at the top + if (bb) bb->resize(r.left, r.top-bb->getHeight(), r.right-r.left, bb->getHeight()+1); + if (tsb) tsb->resize(r.left, r.top-tsb->getHeight(), r.right-r.left, tsb->getHeight()+1); + + // resize content group if it's there + if (contentwnd) { + contentwnd->resize(&r); + // since its holder is not resizing its content, we need to do it ourselves + foreach(tabs) + BaseWnd *c = tabs.getfor()->getBaseWnd(); + if (c->getParent() != NULL && c->getParent() != this && c->getParent()->getParent() == contentwnd->getContentRootWnd()) { + RECT r; + c->getParent()->getClientRect(&r); + c->resize(&r); + } else { + // if we're holding it directly, resize it to our rect + c->resize(&r); + } + endfor + } + + invalidate(); + if (leftscroll) + leftscroll->invalidate(); + if (rightscroll) + rightscroll->invalidate(); + + return 1; +} + +BaseWnd *TabSheet::enumChild(int child) { + TabButtonBase *tb = tabs[child]; + if (tb == NULL) return NULL; + return tb->getBaseWnd(); +} + +int TabSheet::getNumChild() { + return tabs.getNumItems(); +} + +void TabSheet::setCurPage(int page) { + BaseWnd *e = enumChild(page); + if (e != NULL) activateChild(e); +} + +TabButtonBase *TabSheet::enumButton(int i) { + if (i < tabs.getNumItems()) + return tabs[i]; + else + return NULL; +} + +int TabSheet::childNotify(ifc_window *child, int msg, intptr_t param1, intptr_t param2) { + if (msg == ChildNotify::NAMECHANGED) + { + foreach(tabs) + ifc_window *w = tabs.getfor()->getBaseWnd(); + if (w == child || w == child->getParent()) { + const wchar_t *name = child->getRootWndName(); + tabs.getfor()->btn_setText(name && *name ? name : L"[?]"); + } + endfor; + } + if (msg == ChildNotify::GROUPRELOAD && child == contentwnd) { + foreach(tabs) + ifc_window *holder = this; + if (contentwnd->getContentRootWnd() != NULL) { + GuiObject *o = contentwnd->getContent()->guiobject_findObject(L"content"); + if (o != NULL) + holder = o->guiobject_getRootWnd(); + } + tabs.getfor()->getBaseWnd()->reparent(holder); + endfor; + } + return TABSHEET_PARENT::childNotify(child, msg, param1, param2); +} + + +void TabSheet::setContentMarginLeft(int cm) { + content_margin_left = cm; + if (isInited()) + onResize(); +} + +void TabSheet::setContentMarginTop(int cm) { + content_margin_top = cm; + if (isInited()) + onResize(); +} + +void TabSheet::setContentMarginRight(int cm) { + content_margin_right = cm; + if (isInited()) + onResize(); +} + +void TabSheet::setContentMarginBottom(int cm) { + content_margin_bottom = cm; + if (isInited()) + onResize(); +} + +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) { + if (!WCSICMP(action, L"Tabsheet:NextPage")) { nextPage(); return 1; } + if (!WCSICMP(action, L"Tabsheet:PreviousPage")) { previousPage(); return 1; } + return TABSHEET_PARENT::onAction(action, param, x, y, p1, p2, data, datalen, source); +} + +// TabButton + +TabButtonBase::TabButtonBase(BaseWnd *linkwnd, TabSheet *par, const wchar_t *tip) +: linked(linkwnd), parent(par) { + nodeletelinked = 0; + ASSERT(linked != NULL); +} + +TabButtonBase::~TabButtonBase() { + if (!nodeletelinked) delete linked; +} + +int TabButton::onInit() +{ + TABBUTTON_PARENT::onInit(); + setButtonText(linked->getNameSafe(L"[?]")); + return 1; +} + +void TabButton::onLeftPush(int x, int y) { + ASSERT(parent != NULL); + ASSERT(linked != NULL); + parent->activateChild(linked); +} + +void TabButton::btn_setHilite(int tf) { + setHilite(tf); +} + +void TabButton::btn_setText(const wchar_t *text) +{ + setButtonText(text); +} + +// GroupTabButton + +void GroupTabButton::grouptoggle_onLeftPush() { + GROUPTABBUTTON_PARENT::grouptoggle_onLeftPush(); + ASSERT(parent != NULL); + ASSERT(linked != NULL); + parent->activateChild(linked); +} + +void GroupTabButton::btn_setHilite(int tf) { + setStatus(tf ? STATUS_ON : STATUS_OFF); +} + +void GroupTabButton::btn_setText(const wchar_t *text) +{ + for (int i=0;i<getNumGroups();i++) { + GuiObject *grp = enumGroups(i)->getContent(); + if (grp != NULL) { + GuiObject *o = grp->guiobject_findObject(L"text"); + if (o != NULL) { + C_Text txt(o->guiobject_getScriptObject()); + txt.setText(text); + } + } + } +} + +int GroupTabButton::onInit() { + int rt = GROUPTABBUTTON_PARENT::onInit(); + btn_setText(linked->getNameSafe(L"[?]")); + return rt; +} + |