/*
 * widgets/TabbedpaneWidget.cc:
 *
 * Copyright (C) 2000 John Watson, jwatson@tempusmud.com
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

#include "TabbedpaneWidget.h"
#include "ButtonWidget.h"
#include "WidgetEvents.h"
#include "../util/TextureFont.h"

TabbedpaneWidget::TabbedpaneWidget( int w,
                                    int h,
                                    enum TabType type,
                                    int num_widgets,
                                    char ** widget_names,
                                    class Widget ** widgets ) : Widget( w, h ) {
        
        _name = "TabbedPaneWidget";
        _curIndex = 0;
        _numWidgets = num_widgets;
        _widgetNames = widget_names;
        _widgets = widgets;

        _tabType = type;
        _tabListener = new TabListener( this );

        _paneDisplayRect[0][0] = _paneDisplayRect[0][1] = 0;
        _paneDisplayRect[1][0] = _size[0]-1;
        _paneDisplayRect[1][1] = _size[1]-1;
        _fontMargin = _font->getFontHeight() + 8;
        
        switch ( _tabType ) {
        case TAB_TOP:
                _paneDisplayRect[1][1] -= _fontMargin;
                break;
        case TAB_BOTTOM:
                _paneDisplayRect[0][1] += _fontMargin;
                break;
        case TAB_LEFT:
                _paneDisplayRect[0][0] += _fontMargin;
                break;
        case TAB_RIGHT:
                _paneDisplayRect[0][1] -= _fontMargin;
                break;
        }
        
        _tabButtons = new TabButton * [ _numWidgets ];

        int pos[2];

        int buttonpos = 0;

        for ( int i = 0; i < _numWidgets; ++i ) {

                pos[0] = ( _paneDisplayRect[1][0] - _paneDisplayRect[0][0] - _widgets[ i ]->getSize()[0] ) / 2;
                pos[0] += _paneDisplayRect[0][0];

                pos[1] = ( _paneDisplayRect[1][1] - _paneDisplayRect[0][1] - _widgets[ i ]->getSize()[1] ) / 2;
                pos[1] += _paneDisplayRect[0][1];

                add( _widgets[ i ], pos[0], pos[1] );
                
                _widgets[ i ]->setIgnoreEvents( true );
                
                int fontwid = _font->getStringWidth( _widgetNames[i] );
                _tabButtons[ i ] = new TabButton( fontwid + 8, _fontMargin, this, _widgetNames[i] );
                _tabButtons[ i ]->setToggleable( true );
                _tabButtons[ i ]->setDrawMargin( false );
                _tabButtons[ i ]->setSelected( true );

                switch ( _tabType ) {
                case TAB_TOP:
                        pos[0] = buttonpos;
                        pos[1] = _paneDisplayRect[1][1];
                        buttonpos += _tabButtons[ i ]->getSize()[0];
                        break;
                case TAB_BOTTOM:
                        pos[0] = 48 * i;
                        pos[1] = 0;
                        break;
                case TAB_LEFT:
                        pos[0] = 0;
                        pos[1] = 48 * i;
                        break;
                case TAB_RIGHT:
                        pos[0] = _paneDisplayRect[1][0];
                        pos[1] = 48 * i;
                        break;
                }

                add( _tabButtons[ i ], pos[0], pos[1] );
                _tabListener->acceptEventType( EVENT_ACTION, true );
                _tabButtons[ i ]->addWidgetEventListener( _tabListener );

        }

        _tabButtons[ _curIndex ]->setIgnoreEvents( true );
        _tabButtons[ _curIndex ]->setSelected( false );

        setDrawMargin( false );
        setOpaque( true );
        _widgets[ _curIndex ]->setIgnoreEvents( false );
}

void TabbedpaneWidget::paint() {
        Widget::paint();
        
        glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
        glBegin( GL_QUADS );
        {
                glColor4fv( getLookAndFeel()->getSecondaryColor( COLOR_ONE ) );
                    
                glVertex2f( _paneDisplayRect[0][0], _paneDisplayRect[0][1] );
                glVertex2f( _paneDisplayRect[1][0], _paneDisplayRect[0][1] );
                glVertex2f( _paneDisplayRect[1][0], _paneDisplayRect[1][1] );
                glVertex2f( _paneDisplayRect[0][0], _paneDisplayRect[1][1] );
                    
        }
        glEnd();
        glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

        glBegin( GL_LINE_STRIP );
        {
                glColor4fv( getLookAndFeel()->getSecondaryColor( COLOR_TWO ) );
                    
                glVertex2f( _paneDisplayRect[0][0] + 1, _paneDisplayRect[0][1] + 1 );
                glVertex2f( _paneDisplayRect[1][0] - 1, _paneDisplayRect[0][1] + 1 );
                glVertex2f( _paneDisplayRect[1][0] - 1, _paneDisplayRect[1][1] - 1 );

                glColor4fv( getLookAndFeel()->getWhiteColor() );
                    
                glVertex2f( _paneDisplayRect[0][0] + 1, _paneDisplayRect[1][1] - 1 );
                glVertex2f( _paneDisplayRect[0][0] + 1, _paneDisplayRect[0][1] + 1 );
        }
        glEnd();
}

void TabbedpaneWidget::display() {
        //        cout << this << " drawing " << *_widgets[ _curIndex ] << " parent " << _widgets[ _curIndex ]->getParent() << endl;
        glPushMatrix();
        {

                glTranslatef( _pos[0], _pos[1], 0 );
                
                paint();
                
                for ( int i = 0; i < _numWidgets; ++i ) {
                        _tabButtons[i]->display();
                }

                //                cout << this << " drawing " << *_widgets[ _curIndex ] << " parent " << _widgets[ _curIndex ]->getParent() << endl;
                _widgets[ _curIndex ]->display();

        }
        glPopMatrix();
}

void TabbedpaneWidget::setSelectedIndex( int index ) {

        if ( index >= _numWidgets || index < 0 ) {
                cout << " ERROR index " << index << endl;
                return;
        }

        if ( index == _curIndex )
                return;
        
        _widgets[ _curIndex ]->setIgnoreEvents( true );
        _tabButtons[ _curIndex ]->setSelected( true );
        _tabButtons[ _curIndex ]->setIgnoreEvents( false );
        
        _curIndex = index;

        _widgets[ _curIndex ]->setIgnoreEvents( false );
        _tabButtons[ _curIndex ]->setSelected( false );
        _tabButtons[ _curIndex ]->setFocused( false );
        _tabButtons[ _curIndex ]->setIgnoreEvents( true );
}

void TabListener::handleEvent( const class WidgetEvent *evt ) {
        
        if ( evt->getType() == EVENT_ACTION ) {
                class ActionEvent * a_evt = (class ActionEvent *) evt;
                
                //        cout << *evt << endl;
                
                class TabButton * ptr = (class TabButton *) a_evt->getSource();
                
                if ( ptr->isSelected() )
                        return;
                
                for ( int i = 0; i < _pane->_numWidgets; ++i ) {
                        if ( ptr == _pane->_tabButtons[i] ) {
                                if ( i != _pane->_curIndex ) {
                                        _pane->setSelectedIndex( i );
                                }
                                return;
                        }
                }
                cout << " ERROR " << endl;
        }
}


/**
 * default message = 0
 */

TabButton::TabButton( const int width, const int height, 
                      const class TabbedpaneWidget * pane, 
                      const char *message ) : ButtonWidget( width, height, message ) {
        _pane = pane;
        _name = "TabButton";
}

void TabButton::paint() {
        
        glColor4fv( getBGColor4fv() );

        glPushMatrix();
        {

                if ( _pane->_tabType == TAB_BOTTOM ) {
                        glRotatef( 180, 0, 0, 1 );
                        glTranslatef( - _size[0], - _size[1], 0 );
                }

                //
                // descent into the parent tabbed pane if we are the current index
                //
                int bot = isSelected() ? 0 : -2;

                glBegin( GL_POLYGON );
                {
                        glVertex2f( 0,            bot ); 
                        glVertex2f( _size[0] - 1, bot );
                        glVertex2f( _size[0] - 1, _size[1] - 1 );
                        glVertex2f( 4,            _size[1] - 1 );
                        glVertex2f( 0,            _size[1] - 5 );
                }
                glEnd();

                if ( isFocused() ) {
                        glColor4fv( getLookAndFeel()->getHighlightColor() );
                }
                else {
                        glColor4fv( getLookAndFeel()->getSecondaryColor( COLOR_ONE ) );
                }
        
                glBegin( GL_LINE_STRIP );
                {

                        glVertex2f( _size[0] - 1, 0 );
                        glVertex2f( _size[0] - 1, _size[1] - 1 );
                        glVertex2f( 4,            _size[1] - 1 );
                        glVertex2f( 0,            _size[1] - 5 );
                        glVertex2f( 0,            0 );
                        glVertex2f( 1,            0 );
                
                        if ( isSelected() ) {
                                glColor4fv( getLookAndFeel()->getSecondaryColor( COLOR_THREE ) );
                        }
                        else {
                                glColor4fv( getLookAndFeel()->getWhiteColor() );
                        }

                        glVertex2f( 1,            _size[1] - 6 );
                        glVertex2f( 4,            _size[1] - 2 );
                        glVertex2f( _size[0] - 2, _size[1] - 2 );

                }
                glEnd();
        }
        glPopMatrix();
}
