545 lines
13 KiB
C++
545 lines
13 KiB
C++
#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;
|
|
}
|
|
|