| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************/
- // TAB
- /******************************************************************************/
- void Tab:: addChild(GuiObj &child) {_children.add (child, T);}
- void Tab::removeChild(GuiObj &child) {_children.remove(child );}
- Tab& Tab::del()
- {
- _children.del();
- super::del(); return T;
- }
- Tab& Tab::create(C Str &text)
- {
- _children.del();
- super::create(text);
- _type =GO_TAB;
- mode =BUTTON_TOGGLE;
- _sub_type =BUTTON_TYPE_TAB_HORIZONTAL; // set initial sub type (this is the best guess)
- _focusable =false;
- _pixel_align=false;
- return T;
- }
- Tab& Tab::create(C Tab &src)
- {
- if(this!=&src)
- {
- _children.del();
- if(!src.is())del();else
- {
- super::create(src);
- _type=GO_TAB;
- }
- }
- return T;
- }
- Tab& Tab::setCornerTab(Bool right, Bool top)
- {
- _sub_type=(top ? right ? BUTTON_TYPE_TAB_TOP_RIGHT : BUTTON_TYPE_TAB_TOP_LEFT
- : right ? BUTTON_TYPE_TAB_BOTTOM_RIGHT : BUTTON_TYPE_TAB_BOTTOM_LEFT);
- return T;
- }
- Tab& Tab::text(C Str &text)
- {
- if(!Equal(super::text, text, true))
- {
- super::text=text;
- if(parent()->is(GO_TABS)) // Tab rect may depend on text width
- {
- Tabs &tabs=parent()->asTabs();
- if(tabs.autoSize() && tabs.actualLayout()==TABS_HORIZONTAL)tabs.setRect();
- }
- }
- return T;
- }
- Bool Tab::load(File &f, CChar *path)
- {
- del();
- if(super::load(f, path))
- {
- _type=GO_TAB;
- return true;
- }
- return false;
- }
- /******************************************************************************/
- // TABS
- /******************************************************************************/
- void Tabs::zero()
- {
- _valid =false;
- _auto_size =false;
- _layout =_actual_layout=TABS_AUTO;
- _sel =-1;
- _space =0;
- _func =null;
- _func_user =null;
- _func_immediate=false;
- }
- Tabs::Tabs() {zero();}
- Tabs& Tabs::del()
- {
- _tabs.del ();
- _skin.clear();
- super::del(); zero(); return T;
- }
- void Tabs::setButtonSubType()
- {
- // detect first and last visible tab
- Int first_i=0, last_i=0;
- FREPA(T)if(tab(i).visible()){first_i=i; break;}
- REPA(T)if(tab(i).visible()){ last_i=i; break;}
- // setup sub types
- BUTTON_TYPE first, middle, last;
- if(_actual_layout==TABS_HORIZONTAL){first=BUTTON_TYPE_TAB_LEFT; middle=BUTTON_TYPE_TAB_HORIZONTAL; last=BUTTON_TYPE_TAB_RIGHT ;}
- else {first=BUTTON_TYPE_TAB_TOP ; middle=BUTTON_TYPE_TAB_VERTICAL ; last=BUTTON_TYPE_TAB_BOTTOM;}
- REPA(T)
- {
- Tab &tab=T.tab(i);
- if(tab._sub_type<BUTTON_TYPE_TAB_CORNER_START || tab._sub_type>BUTTON_TYPE_TAB_CORNER_END) // if wasn't set to be a corner
- tab._sub_type=((i==first_i) ? first : (i==last_i) ? last : middle);
- }
- }
- void Tabs::setParams()
- {
- _type=GO_TABS;
- REPA(T)
- {
- Tab &tab=T.tab(i); tab._parent=this; tab._pixel_align=false;
- }
- setButtonSubType();
- }
- Tabs& Tabs::create(CChar8 **text, Int num, Bool auto_size)
- {
- del();
- _visible=true;
- _tabs.setNum(num);
- FREPAO(_tabs).create(text ? text[i] : null); // no need to apply skin for tabs because at this point Tabs skin is null
- T._auto_size=auto_size;
- setParams();
- return T;
- }
- Tabs& Tabs::create(CChar **text, Int num, Bool auto_size)
- {
- del();
- _visible=true;
- _tabs.setNum(num);
- FREPAO(_tabs).create(text ? text[i] : null); // no need to apply skin for tabs because at this point Tabs skin is null
- T._auto_size=auto_size;
- setParams();
- return T;
- }
- Tabs& Tabs::create(C Tabs &src)
- {
- if(this!=&src)
- {
- if(!src.is())del();else
- {
- del();
- copyParams(src);
- _type =GO_TABS;
- _skin =src._skin;
- _valid =src._valid;
- _auto_size =src._auto_size;
- _layout =src._layout;
- _actual_layout =src._actual_layout;
- _sel =src._sel;
- _space =src._space;
- _func =src._func;
- _func_user =src._func_user;
- _func_immediate=src._func_immediate;
- _tabs.setNum(src.tabs()); FREPAO(_tabs).create(src.tab(i))._parent=this;
- }
- }
- return T;
- }
- void Tabs::removeChild(GuiObj &child)
- {
- FREPA(T)tab(i).removeChild(child);
- }
- /******************************************************************************/
- Tabs& Tabs::func(void (*func)(Ptr), Ptr user, Bool immediate)
- {
- T._func =func;
- T._func_user =user;
- T._func_immediate=immediate;
- return T;
- }
- void Tabs::call(Bool sound)
- {
- if(sound)Gui.playClickSound();
- if(_func)if(_func_immediate)_func(_func_user);else Gui.addFuncCall(_func, _func_user);
- }
- /******************************************************************************/
- TABS_LAYOUT Tabs::actualLayout()C
- {
- TABS_LAYOUT layout=T.layout();
- if(layout==TABS_AUTO)
- {
- Flt aspect=2.8f, w=rect().w(), h=rect().h();
- layout=((AbsScale((w/_tabs.elms())/h, aspect) < AbsScale(w/(h/_tabs.elms()), aspect)) ? TABS_HORIZONTAL : TABS_VERTICAL);
- }
- return layout;
- }
- void Tabs::setRect()
- {
- if(_tabs.elms())
- {
- Flt w=rect().w(),
- h=rect().h();
- _actual_layout=actualLayout();
- setButtonSubType();
- if(_actual_layout==TABS_HORIZONTAL)
- {
- w-=(_tabs.elms()-1)*space();
- if(autoSize())
- {
- Flt x=rect().min.x, text_width=0, size=h;
- FREPA(T)text_width+=tab(i).textWidth(&size); Flt padd=(w-text_width)/_tabs.elms();
- FREPA(T)
- {
- Tab &tab=T.tab(i); Flt w=tab.textWidth(&size)+padd;
- tab.rect(Rect(x, rect().min.y, x+w, rect().max.y));
- x+=w+space();
- }
- }else
- {
- w/=_tabs.elms();
- REPA(T)tab(i).rect(Rect(rect().min.x+(w+space())*i, rect().min.y, rect().min.x+(w+space())*i+w, rect().max.y));
- }
- }else
- {
- h-=(_tabs.elms()-1)*space(); h/=_tabs.elms();
- REPA(T)tab(i).rect(Rect(rect().min.x, rect().max.y-(h+space())*i-h, rect().max.x, rect().max.y-(h+space())*i));
- }
- }
- }
- Tabs& Tabs::rect(C Rect &rect, Flt space, Bool auto_size)
- {
- if(T.rect()!=rect || T.space()!=space || T.autoSize()!=auto_size)
- {
- T._rect =rect;
- T._space =space;
- T._auto_size=auto_size;
- setRect();
- }
- return T;
- }
- /******************************************************************************/
- Tabs& Tabs::rect(C Rect &rect) {return T.rect(rect, space(), autoSize());}
- /******************************************************************************/
- Tabs& Tabs::layout(TABS_LAYOUT layout)
- {
- MIN(layout, TABS_NUM);
- if(T.layout()!=layout)
- {
- T._layout=layout;
- setRect();
- }
- return T;
- }
- /******************************************************************************/
- Tabs& Tabs::valid(Bool on) {T._valid=on; return T;}
- Tabs& Tabs::set(Int i, SET_MODE mode)
- {
- if(!InRange(i, _tabs))
- {
- if(valid())return T; // don't set to -1 if 'valid' is enabled
- i=-1; // set sel to -1
- }
- if(T()!=i)
- {
- Bool kb=contains(Gui.kb());
- if(valid() && InRange(T(), T)) // set highlight for previously selected tab if there's a hoverable MT above it
- {
- Tab &tab=T.tab(T());
- Bool lit=false; if(enabled())REPA(MT)if(MT.guiObj(i)==&tab && MT.hoverable(i)){lit=true; break;}
- tab._lit=lit;
- }
- _sel=i; REPAD(j, T)tab(j).set(i==j);
- if(valid() && InRange(T(), T))tab(T())._lit=0; // disable highlight for newly selected tab
- if(kb)if(InRange(T(), T))tab(T()).kbSet();else kbSet();
- if(mode!=QUIET)call(mode!=NO_SOUND);
- }
- return T;
- }
- Tabs& Tabs::toggle(Int i, SET_MODE mode) {return set((T()==i) ? -1 : i, mode);}
- /******************************************************************************/
- Tabs& Tabs::skin(C GuiSkinPtr &skin)
- {
- _skin=skin;
- REPAO(_tabs).skin=skin;
- return T;
- }
- /******************************************************************************/
- Tabs& Tabs::move(C Vec2 &delta)
- {
- if(delta.any())
- {
- super::move(delta);
- REPA(T)tab(i).move(delta);
- }
- return T;
- }
- /******************************************************************************/
- Tab& Tabs::New(C Str &text, Int i)
- {
- if(i<0)i=tabs();else if(i>tabs())i=tabs();
- if(_sel>=i)_sel++;
- Tab &tab=_tabs.NewAt(i).create(text); tab._parent=this; tab.skin=skin();
- setRect();
- return tab;
- }
- Tabs& Tabs::remove(Int i)
- {
- if(InRange(i, T))
- {
- if(_sel==i)_sel=-1;else
- if(_sel> i)_sel--;
- _tabs.removeValid(i, true);
- setRect();
- }
- return T;
- }
- /******************************************************************************/
- Tabs& Tabs::desc(C Str &desc)
- {
- super::desc(desc);
- REPA(T)tab(i).desc(desc);
- return T;
- }
- /******************************************************************************/
- GuiObj* Tabs::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel)
- {
- if(visible() && gpc.visible && Cuts(pos, gpc.clip))
- {
- if(InRange(T(), T))if(GuiObj *go=tab(T())._children.test(gpc, pos, mouse_wheel))return go;
- if(Cuts(pos, rect()+gpc.offset))
- {
- REPA(T)if(GuiObj *go=tab(i).test(gpc, pos, mouse_wheel))return go;
- //return this; // don't return self
- }
- }
- return null;
- }
- /******************************************************************************/
- void Tabs::update(C GuiPC &gpc)
- {
- GuiPC gpc2(gpc, visible(), enabled());
- Bool enabled=gpc2.enabled;
- FREPA(T)
- {
- gpc2.enabled=(enabled && !(valid() && i==T())); // force disabled if 'valid' is enabled and we're processing activated Tab (this way we can't click pushed Tab)
- Tab &tab=T.tab(i); tab.update(gpc2);
- if((T()==i)!=tab())toggle(i); // if Tab update state changed
- }
- gpc2.enabled=enabled; // restore 'enabled' after loop, because it was changed inside it
- Bool visible=gpc2.visible;
- FREPA(T)
- {
- gpc2.visible=(visible && i==T());
- tab(i)._children.update(gpc2);
- }
- }
- void Tabs::draw(C GuiPC &gpc)
- {
- if(visible() && gpc.visible)
- {
- setButtonSubType();
- Rect r=rect()+gpc.offset; Vec2 ofs=D.alignScreenToPixelOffset(r.lu()); r+=ofs;
- GuiPC gpc2(gpc, visible(), enabled()); gpc2.offset+=ofs; // adjust offset so that all tabs have the same pixel alignment as the first one
- FREPA(T) tab(i ). draw(gpc2);
- if(T()>=0)tab(T())._children.draw(gpc );
- }
- }
- /******************************************************************************/
- Bool Tabs::save(File &f, CChar *path)C
- {
- if(super::save(f, path))
- {
- f.putMulti(Byte(1), _valid, _auto_size, _sel, _space, _layout); // version
- f._putAsset(_skin.name(path));
- f.cmpUIntV(_tabs.elms()); FREPA(_tabs)if(!_tabs[i].save(f, path))return false;
- return f.ok();
- }
- return false;
- }
- Bool Tabs::load(File &f, CChar *path)
- {
- del(); if(super::load(f, path))switch(f.decUIntV()) // version
- {
- case 1:
- {
- f.getMulti(_valid, _auto_size, _sel, _space, _layout);
- _skin.require(f._getAsset(), path);
- _tabs.clear().setNum(f.decUIntV()); FREPA(_tabs)if(!_tabs[i].load(f, path))goto error;
- if(f.ok())
- {
- _actual_layout=actualLayout();
- setParams();
- return true;
- }
- }break;
- case 0:
- {
- f._getStr();
- f>>_valid>>_auto_size>>_sel>>_space>>_layout;
- _tabs.clear().setNum(f.getInt()); FREPA(_tabs){Tab &tab=_tabs[i]; if(!tab.load(f, path))goto error; tab.enabled(true);} // restore enabled because in the past tabs were disabled on click
- if(f.ok())
- {
- _actual_layout=actualLayout();
- setParams();
- return true;
- }
- }break;
- }
- error:
- del(); return false;
- }
- /******************************************************************************/
- void Tab::parentClientRectChanged(C Rect *old_client, C Rect *new_client)
- {
- notifyChildrenOfClientRectChange(old_client, new_client); // pass on to the children
- }
- void Tabs::parentClientRectChanged(C Rect *old_client, C Rect *new_client)
- {
- notifyChildrenOfClientRectChange(old_client, new_client); // pass on to the children
- }
- /******************************************************************************/
- }
- /******************************************************************************/
|