//----------------------------------------------------------------------------- // VST Plug-Ins SDK // VSTGUI: Graphical User Interface Framework not only for VST plugins : // // CTabView written 2004 by Arne Scheffler // //----------------------------------------------------------------------------- // VSTGUI LICENSE // © 2004, Steinberg Media Technologies, All Rights Reserved //----------------------------------------------------------------------------- // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of the Steinberg Media Technologies nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. //----------------------------------------------------------------------------- #ifndef __ctabview__ #include "ctabview.h" #endif BEGIN_NAMESPACE_VSTGUI #define kTabButtonTagStart 20000 //----------------------------------------------------------------------------- class CTabButton : public COnOffButton //----------------------------------------------------------------------------- { public: CTabButton (const CRect &size, CControlListener *listener, long tag, CBitmap *background, const char* inName) : COnOffButton (size, listener, tag, background) , name (0) { if (inName) { name = (char*)malloc (strlen (inName) + 1); strcpy (name, inName); } activeTextColor = kBlackCColor; inactiveTextColor (90, 90, 90, 255); textFont = kSystemFont; fontSize = 12; } virtual ~CTabButton () { if (name) free (name); } virtual void draw (CDrawContext *pContext) { COnOffButton::draw (pContext); if (name) { pContext->setFont (textFont, fontSize); pContext->setFontColor (value ? activeTextColor : inactiveTextColor); pContext->drawString (name, size, false); } } void mouse (CDrawContext *pContext, CPoint &where, long button) { if (!bMouseEnabled) return; if (button == -1) button = pContext->getMouseButtons (); if (!(button & kLButton)) return; value = ((long)value) ? 0.f : 1.f; if (listener) listener->valueChanged (pContext, this); } virtual void onDragEnter (CDrawContext* context, CDragContainer* drag, const CPoint& where) { if (value == 0.f) { value = 1.f; if (listener) listener->valueChanged (context, this); } } void setTextFont (const CFont& font) { textFont = font; } void setActiveTextColor (const CColor& color) { activeTextColor = color; } void setInactiveTextColor (const CColor& color) { inactiveTextColor = color; } void setTextSize (const long& textSize) { fontSize = textSize; } CLASS_METHODS (CTabButton, COnOffButton) protected: char* name; CFont textFont; CColor activeTextColor; CColor inactiveTextColor; long fontSize; }; //----------------------------------------------------------------------------- class CTabChildView : public CReferenceCounter //----------------------------------------------------------------------------- { public: CTabChildView (CView* view) : view (view) , previous (0) , next (0) , button (0) { } virtual ~CTabChildView () { view->forget (); } CView* view; CTabChildView* previous; CTabChildView* next; CTabButton* button; }; //----------------------------------------------------------------------------- CTabView::CTabView (const CRect& size, CFrame* parent, CBitmap* tabBitmap, CBitmap* background, long tabPosition, long style) : CViewContainer (size, parent, background) , numberOfChilds (0) , tabPosition (tabPosition) , style (style) , tabSize (CRect (0, 0, 0, 0)) , tabBitmap (tabBitmap) , firstChild (0) , lastChild (0) , currentChild (0) { if (tabBitmap) { tabBitmap->remember (); tabSize.right = tabBitmap->getWidth (); tabSize.bottom = tabBitmap->getHeight (); } setMode (kOnlyDirtyUpdate); } //----------------------------------------------------------------------------- CTabView::CTabView (const CRect& size, CFrame* parent, const CRect& tabSize, CBitmap* background, long tabPosition, long style) : CViewContainer (size, parent, background) , numberOfChilds (0) , tabPosition (tabPosition) , style (style) , tabSize (tabSize) , tabBitmap (0) , firstChild (0) , lastChild (0) , currentChild (0) { setMode (kOnlyDirtyUpdate); } //----------------------------------------------------------------------------- CTabView::~CTabView () { pParentFrame = 0; removeAllTabs (); if (tabBitmap) tabBitmap->forget (); } //----------------------------------------------------------------------------- bool CTabView::addTab (CView* view, const char* name, CBitmap* tabBitmap) { if (!view) return false; if (tabBitmap == 0) tabBitmap = this->tabBitmap; CRect ts (0, 0, tabSize.getWidth (), tabSize.getHeight () / 2); switch (tabPosition) { case kPositionTop: ts.offset (tabSize.getWidth () * numberOfChilds, 0); break; case kPositionBottom: ts.offset (tabSize.getWidth () * numberOfChilds, size.getHeight () - tabSize.getHeight () / 2); break; case kPositionLeft: ts.offset (0, tabSize.getHeight () / 2 * numberOfChilds); break; case kPositionRight: ts.offset (size.getWidth () - tabSize.getWidth (), tabSize.getHeight () / 2 * numberOfChilds); break; } CTabButton* b = new CTabButton (ts, this, numberOfChilds + kTabButtonTagStart, tabBitmap, name); b->setTransparency (true); addView (b); CTabChildView* v = new CTabChildView (view); v->button = b; if (lastChild) { lastChild->next = v; v->previous = lastChild; lastChild = v; } else { firstChild = lastChild = v; setCurrentChild (v); } numberOfChilds++; return true; } //----------------------------------------------------------------------------- bool CTabView::removeTab (CView* view) { if (!view) return false; CTabChildView* v = firstChild; while (v) { if (v->view == view) { if (v->previous) v->previous->next = v->next; if (v->next) v->next->previous = v->previous; if (v == currentChild) setCurrentChild (v->previous ? v->previous : v->next); removeView (v->button, true); v->forget (); numberOfChilds--; return true; } v = v->next; } return false; } //----------------------------------------------------------------------------- bool CTabView::removeAllTabs () { setCurrentChild (0); CTabChildView* v = lastChild; while (v) { CTabChildView* next = v->previous; removeTab (v->view); v = next; } firstChild = 0; lastChild = 0; numberOfChilds = 0; return true; } //----------------------------------------------------------------------------- bool CTabView::selectTab (long index) { if (index > (long)numberOfChilds) return false; CTabChildView* v = firstChild; long i = 0; while (v) { if (index == i) break; v = v->next; i++; } if (v) { setCurrentChild (v); return true; } return false; } //----------------------------------------------------------------------------- void CTabView::setCurrentChild (CTabChildView* childView) { if (childView == currentChild) { if (currentChild->button) currentChild->button->setValue (1.f); return; } if (currentChild) { if (currentChild->button) currentChild->button->setValue (0.f); removeView (currentChild->view, false); } currentChild = childView; if (currentChild) { addView (currentChild->view); if (currentChild->button) currentChild->button->setValue (1.f); } setDirty (); } //----------------------------------------------------------------------------- void CTabView::valueChanged (CDrawContext *pContext, CControl *pControl) { if (pControl->isTypeOf ("CTabButton")) selectTab (pControl->getTag () - kTabButtonTagStart); } //----------------------------------------------------------------------------- CRect& CTabView::getTabViewSize (CRect& rect) const { rect = size; rect.offset (-size.left, -size.top); switch (tabPosition) { case kPositionTop: rect.top += tabSize.getHeight () / 2; break; case kPositionBottom: rect.bottom -= tabSize.getHeight () / 2; break; case kPositionLeft: rect.left += tabSize.getWidth (); break; case kPositionRight: rect.right -= tabSize.getWidth (); break; } return rect; } //----------------------------------------------------------------------------- void CTabView::setTabFontStyle (const CFont& font, long fontSize, CColor selectedColor, CColor deselectedColor) { CTabChildView* v = firstChild; while (v) { v->button->setTextFont (font); v->button->setTextSize (fontSize); v->button->setActiveTextColor (selectedColor); v->button->setInactiveTextColor (deselectedColor); v = v->next; } } //----------------------------------------------------------------------------- void CTabView::alignTabs (long alignment) { CCoord allTabsWidth; CCoord viewWidth; CCoord offset = 0; CRect ts (0, 0, tabSize.getWidth (), tabSize.getHeight () / 2); if (tabPosition == kPositionTop || tabPosition == kPositionBottom) { allTabsWidth = tabSize.getWidth () * numberOfChilds; viewWidth = size.getWidth (); } else { allTabsWidth = (tabSize.getHeight () / 2) * numberOfChilds; viewWidth = size.getHeight (); } if (alignment == kAlignCenter) offset = (viewWidth - allTabsWidth) / 2; else if (alignment == kAlignLeft) offset = 0; else if (alignment == kAlignRight) offset = viewWidth - allTabsWidth; if (tabPosition == kPositionTop) ts.offset (offset, 0); else if (tabPosition == kPositionBottom) ts.offset (offset, size.getHeight () - tabSize.getHeight () / 2); else if (tabPosition == kPositionLeft) ts.offset (0, offset); else if (tabPosition == kPositionRight) ts.offset (size.getWidth () - tabSize.getWidth (), offset); CTabChildView* v = firstChild; while (v) { v->button->setViewSize (ts); v->button->setMouseableArea (ts); if (tabPosition == kPositionTop || tabPosition == kPositionBottom) ts.offset (tabSize.getWidth (), 0); else ts.offset (0, tabSize.getHeight () / 2); v = v->next; } setDirty (true); } END_NAMESPACE_VSTGUI