/*
(c) CopyLeft 2003, 2004 Benn Herrera benn@bennherrera.com
Permission granted to copy, use, and modify this code so long as this notice is left intact.
If this code is used in any commercial product, appropriate attribution is required.
Full terms at http://www.gnu.org/copyleft/gpl.html
*/
//
// this file contains definitions of custom button and input control classes
//

var JSTFocusCtl = null;

function jstCtlOnKeyDown( e ) {
    if ( !JSTFocusCtl )
        return false;
        
    return JSTFocusCtl.jstCtlOnKeyDown( e );
}

function jstCtlOnKeyUp( e ) {
    if ( !JSTFocusCtl )
        return false;
     
    return JSTFocusCtl.jstCtlOnKeyUp( e );
}

function jstGetKeyCode( e ) {
	if( typeof( e.which ) == 'number' ) {
        //NS 4, NS 6+, Mozilla 0.9+, Opera
        return e.which;
    } else if( typeof( e.keyCode ) == 'number'  ) {
        //IE, NS 6+, Mozilla 0.9+
        return e.keyCode;
    } else if( typeof( e.charCode ) == 'number'  ) {
        //also NS 6+, Mozilla 0.9+
        return e.charCode;
	}
    
    return 0;
}

function getCtl( id ) {
    return document.getElementById( id );
}

/*
 * base control class
 */
 
function getJSTCtl( elem ) {    
    if ( typeof( elem ) == "string" ) {
        elem = document.getElementById( elem );
    }
    
    return elem.jstCtl;
}

function jstCtlOnMouseOver( elem ) {
    if ( !elem.jstCtl.enabled )
        return;
    
    elem.jstCtl.mouseOver = true;
    elem.jstCtl.jstCtlOnMouseOver();
}

function jstCtlOnMouseOut( elem ) {
    if ( !elem.jstCtl.enabled )
        return;
    
    elem.jstCtl.mouseOver = false;
    elem.jstCtl.jstCtlOnMouseOut();
}

function jstCtlOnMouseDown( elem ) {
    if ( !elem.jstCtl.enabled )
        return;
    
    elem.jstCtl.jstCtlOnMouseDown();
}

function jstCtlOnMouseUp( elem ) {
    if ( !elem.jstCtl.enabled )
        return;
    
    elem.jstCtl.jstCtlOnMouseUp();
}

function jstCtlEnable( enabled ) {
    this.enabled = enabled;
    this.jstCtlDraw();
}

function JSTControl( cell ) {   
    this.eventHandlers = " onMouseDown=\"jstCtlOnMouseDown(this)\" onMouseUp=\"jstCtlOnMouseUp(this)\""   +
                         " onMouseOver=\"jstCtlOnMouseOver(this)\" onMouseOut=\"jstCtlOnMouseOut(this)\" ";
                         
    this.jstCtlEnable  = jstCtlEnable;
    this.mouseOver     = false;
    this.enabled       = true;
    this.cell          = cell;
    
    if ( !this.cell )
        return;
    
    var tHTML = "<div " + this.eventHandlers + ">" +
                this.cell.innerHTML +
                "</div>";
        
    this.cell.innerHTML              = tHTML;
    this.cell.style.height           = "16px";
    this.cell.style.fontSize         = "12px"
    this.cell.style.borderStyle      = "solid";
    this.cell.style.borderWidth      = "2px";

    this.cell.firstChild.jstCtl      = this;
    this.cell.firstChild.style.width = "100%";
    this.cell.jstCtl                 = this;
}

/*
 * button class
 */

function jstBtnOnMouseOver() {
    JSTFocusCtl = this;
    this.jstCtlDraw();
}

function jstBtnOnMouseOut() {
    JSTFocusCtl = null;
    this.jstCtlDraw();
}

function jstBtnOnMouseDown() {
    this.cell.style.color       = this.mouseDownLabelColor;
    this.cell.style.borderColor = this.mouseDownBorderColor;
    this.cell.style.background  = this.mouseDownBackgroundColor;
}

function jstBtnOnMouseUp() {    
    if ( this.callback ) {
        this.callback( this );
    }
    
    this.jstCtlDraw();
}

function jstBtnDraw() {
    if ( !this.enabled ) {
        this.cell.style.color       = this.disabledLabelColor;
        this.cell.style.borderColor = this.disabledBorderColor;
        this.cell.style.background  = this.disabledBackgroundColor;
    } else if ( this.mouseOver ) {
        this.cell.style.color       = this.mouseOverLabelColor;
        this.cell.style.borderColor = this.mouseOverBorderColor;
        this.cell.style.background  = this.mouseOverBackgroundColor;
    } else {
        this.cell.style.color       = this.labelColor;
        this.cell.style.borderColor = this.borderColor;
        this.cell.style.background  = this.backgroundColor;
    }
}

function jstBtnOnKeyDown( e ) {
    var keyCode = jstGetKeyCode( e );
    
    // enter or space down, button down
    if ( keyCode == 13 || keyCode == 32 ) {
        this.jstCtlOnMouseDown();
        return true;
    }
    
    return false;
}

function jstBtnOnKeyUp( e ) {
    var keyCode = jstGetKeyCode( e );
    
    // enter or space up, button up
    if ( keyCode == 13 || keyCode == 32 ) {
        this.jstCtlOnMouseUp();
        return true;
    }
    
    return false;
}

function jstBtnSetLabel( label ) {
    this.label = label;
    //this.cell.firstChild.innerHTML = this.label;
}

function jstBtnGetLabel() {
    return this.label;
}

function JSTButton( cell, callback,
                    labelColor, borderColor, bgColor,
                    moLabelColor, moBorderColor, moBgColor,
                    mdLabelColor, mdBorderColor, mdBgColor,
                    disLabelColor, disBorderColor, disBgColor,
                    label ) {
                        
    this.base = JSTControl; 
    this.base( cell );
     
    this.callback                 = callback;
    
    this.labelColor               = labelColor;
    this.borderColor              = borderColor;
    this.backgroundColor          = bgColor;
    
    this.mouseOverLabelColor      = moLabelColor
    this.mouseOverBorderColor     = moBorderColor;
    this.mouseOverBackgroundColor = moBgColor;
    
    this.mouseDownLabelColor      = mdLabelColor;
    this.mouseDownBorderColor     = mdBorderColor;
    this.mouseDownBackgroundColor = mdBgColor;
    
    this.disabledLabelColor       = disLabelColor;
    this.disabledBorderColor      = disBorderColor;
    this.disabledBackgroundColor  = disBgColor;
    
    this.setLabel                 = jstBtnSetLabel;
    this.getLabel                 = jstBtnGetLabel;
    this.jstCtlOnMouseOver        = jstBtnOnMouseOver;
    this.jstCtlOnMouseOut         = jstBtnOnMouseOut;
    this.jstCtlOnMouseDown        = jstBtnOnMouseDown;
    this.jstCtlOnMouseUp          = jstBtnOnMouseUp;
    this.jstCtlOnKeyDown          = jstBtnOnKeyDown;
    this.jstCtlOnKeyUp            = jstBtnOnKeyUp;
    
    this.jstCtlDraw               = jstBtnDraw;
    
    if ( this.cell ) {
        this.cell.firstChild.style.width = "100%";
            
        if ( label )
            this.setLabel( label );
        
        this.jstCtlDraw();
    }
}

JSTButton.prototype = new JSTControl;

//
// config buttons - gray text
//
function JSTConfigButton( cell, callback, label ) {     
    var labelColor     = "#c0c0c0";
    var borderColor    = "gray";
    var bgColor        = "black";
    
    var moLabelColor   = "white";
    var moBorderColor  = "#c0c0c0";
    var moBgColor      = "black";
    
    var mdLabelColor   = "#a0a0a0";
    var mdBorderColor  = "#a0a0a0";
    var mdBgColor      = "black";
    
    var disLabelColor  = "#5f5f5f";
    var disBorderColor = "#3f3f3f";
    var disBgColor     = "black";
    
    this.base = JSTButton      
    this.base( cell, callback,
               labelColor, borderColor, bgColor,
               moLabelColor, moBorderColor, moBgColor,
               mdLabelColor, mdBorderColor, mdBgColor,
               disLabelColor, disBorderColor, disBgColor,
               label );
}

JSTConfigButton.prototype = new JSTButton;


//
// game buttons - colored text
//
function JSTGameButton( cell, callback, label ) {   
    var labelColor     = "orange";
    var borderColor    = "gray";
    var bgColor        = "black";
    
    var moLabelColor   = "yellow";
    var moBorderColor  = "#c0c0c0";
    var moBgColor      = "black";
    
    var mdLabelColor   = "red";
    var mdBorderColor  = "#a0a0a0";
    var mdBgColor      = "black";
    
    var disLabelColor  = "#5f5f5f";
    var disBorderColor = "#3f3f3f";
    var disBgColor     = "black";
    
    this.base = JSTButton;
    this.base( cell, callback,
               labelColor, borderColor, bgColor,
               moLabelColor, moBorderColor, moBgColor,
               mdLabelColor, mdBorderColor, mdBgColor,
               disLabelColor, disBorderColor, disBgColor,
               label );
}

JSTGameButton.prototype = new JSTButton;

/*
 * edit class
 */
 
function jstEdtOnMouseOver() {   
    JSTFocusCtl = this;
    
    this.jstCtlDraw();
}

function jstEdtOnMouseOut() {
    JSTFocusCtl = null;

    this.jstCtlDraw();
    
    if ( this.focusLostCB )
        this.focusLostCB( this );
}

function jstEdtDraw() {
    if ( !this.enabled ) {
        this.cell.style.color       = this.disabledTextColor;
        this.cell.style.borderColor = this.disabledBorderColor;
        this.cell.style.background  = this.disabledBackgroundColor;
    } else if ( JSTFocusCtl == this ) {
        this.cell.style.color       = this.focusTextColor;
        this.cell.style.borderColor = this.focusBorderColor;
        this.cell.style.background  = this.focusBackgroundColor;
        this.showValue();
    } else {
        this.cell.style.color       = this.textColor;
        this.cell.style.borderColor = this.borderColor;
        this.cell.style.background  = this.backgroundColor;
    }
    
    this.showValue();
}

function jstEdtGetPrintable( e ) {
    var code     = jstGetKeyCode( e );
    var kpNumber = false;
    var number   = false;
       
    if ( e.altKey || e.ctrlCkey || e.metaKey )
        return 0;
       
    // space
    if ( code == 32 )
        return ' ';
    
    // letters
    if ( code >= 65 && code <= 90 ) {
        if ( e.shiftKey )
            return String.fromCharCode( code ).toUpperCase();
        return String.fromCharCode( code ).toLowerCase();
    }
    
    // symbols
    if ( code >= 186 && code <= 192 ) {
        if ( e.shiftKey )
            return (":+<_>?~").charAt( code - 186 );
        
        return (";=,-./`").charAt( code - 186 );
    }
    
    // symbols
    if ( code >= 219 && code <= 222 ) {
        if ( e.shiftKey )
            return ("{|}\"").charAt( code - 219 );
        
        return ("[\\]'").charAt( code - 219 );
    }
    
    // kp symbols
    if ( code >= 106 && code <= 111 ) {
        return ("*+|-./").charAt( code - 106 );
    }
    
    // numbers
    if ( code >= 48 && code <= 57 ) {
        number = true;
    // kp numbers
    } else if ( code >= 96 && code <= 105 ) {
        kpNumber = true;
        code -= 48;
    }
    
    if ( number || kpNumber ) {
        if ( number && e.shiftKey )
            return (")!@#$%^&*(").charAt( code - 48 );
        
        return ("0123456789").charAt( code - 48 );
    }

    return 0;
}

function jstEdtOnKeyDown( e ) {    
    var keyCode = jstGetKeyCode( e );
    
    if ( !keyCode )
        return true;
    
    var changed   = true;
    var typedChar = 0;
    
	switch( keyCode ) {
	// left / down
    case 37:
    case 40:
	    this.position = (this.position > 1) ? (this.position - 1) : 0; 
        changed = false
        break;
        
    // right / up
    case 38:
    case 39:
        this.position = ( (this.position >= this.value.length) ? this.value.length : (this.position + 1) );
        changed = false;
        break;
    
    // delete
    case 46:
        if ( this.value.length == 0 || this.position >= this.value.length )
            return;
        
        this.value = this.value.substr( 0, this.position ) + this.value.substr( this.position + 1 );   
        break;
    
    // backspace
    case  8:
        if ( this.value.length == 0 || this.position <= 0 ) 
            return;
        
        this.value = this.value.substr( 0, this.position - 1 ) + this.value.substr( this.position );
        this.position--;
        break;
    
    default:
        if ( (typedChar = this.getPrintable( e )) && this.value.length < this.maxLength ) {
            this.value = this.value.substr( 0, this.position ) + typedChar + this.value.substr( this.position );
            this.position++;
        }
	}
      
    this.showValue();
    
    if ( changed && this.changedCB )
        this.changedCB( this );
    
    return true;
}

function jstEdtOnKeyUp( e ) {
    return true;
}

function jstEdtOnMouseDown() {
}

function jstEdtOnMouseUp() {
}

function jstEdtSetValue( value ) {
    this.value = value.toString();
    
    if ( this.changedCB )
        this.changedCB( this );
    
    this.showValue();
}

function jstEdtGetValue() {
    return this.value;
}

function jstEdtShowValue() {
    if ( JSTFocusCtl == this ) {       
        var left   = this.value.substr( 0, this.position );
        var right  = this.value.substr( this.position );
        var cursor = "<span style=\"font-height: 16px; "           +
                       "font-width:  1px; "                        +
                       "font-weight: light; "                      +
                       "color: " + this.cursorColor      + ";\">"  +
                       "|</span>";
            
        this.cell.firstChild.innerHTML = left + cursor + right;
    } else {
        this.cell.firstChild.innerHTML = this.value;
    }
}

function JSTEdit( cell, changedCB, focusLostCB ) {
    this.base = JSTControl;
    this.base( cell );
    
    this.textColor               = "black";
    this.borderColor             = "gray";
    this.backgroundColor         = "#ffffd0";
    
    this.focusTextColor          = "black";
    this.focusBorderColor        = "#c0c0c0";
    this.focusBackgroundColor    = "white";
    
    this.disabledTextColor       = "#3f3f3f";
    this.disabledBorderColor     = "#3f3f3f";
    this.disabledBackgroundColor = "#7f7f70";
    
    this.cursorColor             = "blue";
                                
    this.position                = 0;
    this.value                   = "";
       
    this.jstCtlOnMouseOver       = jstEdtOnMouseOver;
    this.jstCtlOnMouseOut        = jstEdtOnMouseOut;
    this.jstCtlOnMouseDown       = jstEdtOnMouseDown;
    this.jstCtlOnMouseUp         = jstEdtOnMouseUp;
    this.jstCtlOnKeyDown         = jstEdtOnKeyDown;
    this.jstCtlOnKeyUp           = jstEdtOnKeyUp;
    this.jstCtlDraw              = jstEdtDraw;
    
    this.getValue                = jstEdtGetValue;
    this.setValue                = jstEdtSetValue;
    this.showValue               = jstEdtShowValue;
    this.getPrintable            = jstEdtGetPrintable;
    
    this.changedCB               = changedCB;
    this.focusLostCB             = focusLostCB;
    
    this.maxLength               = NaN;
    
    if ( this.cell )
        this.maxLength = this.cell.jstWidth ? parseInt( this.cell.jstWidth ) : NaN;
    
    if ( this.maxLength == NaN )
        this.maxLength = 10;
      
    if ( this.cell ) {
        this.cell.style.width = (this.maxLength * 8) + "px";
    
        this.jstCtlDraw();
    }
}

JSTEdit.prototype = new JSTControl;

