//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>
#include <WSkeysym.h>
#include <WSDkeyboard.h>
#include <WSCvradio.h>
#include <WSCclassInformation.h>
#include <WSDdev.h>
#include <WSCdevice.h>
#include <WSCimageSet.h>
#include <WSDtimer.h>
#include <WSCfontSet.h>
#include <WSCblink.h>
#include <WSDappDev.h>

WSMFguiClassInitialize(WSCvradio,WSCvtoggle);
WSMFversion(WSCvradio,WSCvtoggle);

#define WS_WORK_NORMAL       0
#define WS_WORK_CURSOR_CLEAR 1

WSMFpropertyValueChange(WSCvradio,WSNindicatorColor,short,WS_DF_WORKBACKCOLOR);
WSMFpropertyValueChange(WSCvradio,WSNindicatorSize,WSCuchar,16);

WSCvradio::WSCvradio(WSCbase* base,char* objname):
                WSCvtoggle(base,objname){

  _indicator_color = WS_DF_WORKBACKCOLOR;
  _indicator_size = 16;

  WSMFpropertyCreateStart
      WSMFparentCheckVerSrc(WSCvradio);

      WSMFpropertyDelete(WSNindicatorOn);
      WSMFpropertyDelete(WSNindicatorType);
      WSMFpropertyDelete(WSNindicatorPixmap);
      WSMFpropertyDelete(WSNselectPixmap);
      WSMFpropertyDelete(WSNshadowType);
      WSMFpropertyDelete(WSNindicatorShadow);

    WSMFpropertyValueChangeDef(WSCvradio,WSNindicatorColor,short);
    WSMFpropertyValueChangeDef(WSCvradio,WSNindicatorSize,WSCuchar);


  WSMFpropertyCreateEnd
}
long WSCvradio::draw(){
  if (getVisible() == False){
    return WS_NO_ERR;
  }

  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }

  short x = _x;
  short y = _y;
  WSCushort w = _w;
  WSCushort h = _h;

  WSCbool absolute = getAbsoluteDraw();
  if (absolute == True){

  }else if (dev->isExposed(x, y, w, h) == False ){
    return WS_NO_ERR;
  }

  WSCushort st = _shadow_thick;
  long blinking   = _bl_fl;
  long blinkfore  = WSGIappBlink()->getBlinkFore(_blink_rate);
  long shadowtype = _shadow_type;
  long twinblink  = _tw_fl;
  long blinktype  = _bl_type;
  short fgno         = _fore_color;
  short bgno         = _back_color;
  short blinkcolorno = _blink_color;
  short backblinkno  = _bg_blink_color;
  short tsno         = _ts_color;
  short bsno         = _bs_color;

  if ( shadowtype == WS_SHADOW_NONE &&
       blinking  != False &&
       blinkfore != False &&
       twinblink == False){
    return WS_NO_ERR;
  }
  if (WSGIappDev()->getExtGuiPolicySelected() != False){
    if (_ext_draw_proc == NULL){
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->
                               getExtGuiPolicyProc("WSCvradio::draw");
    }
    if (_ext_draw_proc != NULL){
      WSCvtoggle_draw_struct st;
      st._this = this;
      st.dev = dev;
      st.x = _x;
      st.y = _y;
      st.width = _w;
      st.height = _h;
      st.shadow_thickness = _shadow_thick;
      st.blinking = _bl_fl;
      st.blink_fore = WSGIappBlink()->getBlinkFore(_blink_rate);
      st.shadow_type = _shadow_type;
      st.blink_type  = _bl_type;
      st.twin_blink   = _tw_fl;
      st.fore_color   = _fore_color;
      st.back_color   = _back_color;
      st.blink_color  = _blink_color;
      st.select_color = _select_color;
      st.back_blink_color = _bg_blink_color;
      st.top_shadow_color = _ts_color;
      st.bottom_shadow_color = _bs_color;
      st.label_string = _label_string;
      st.select_string = _select_string;
      st.label_pixmap = _label_pixmap;
      st.blink_pixmap = _blink_pixmap;
      st.select_pixmap = _select_pixmap;
      st.press_status = _press_status;
      st.orientation = _orientation;
      st.gradation = _grad_no;
      st.gradation_margin = _grad_margin;
      st.margin_left = _margin_left;
      st.margin_right = _margin_right;
      st.margin_top = _margin_top;
      st.margin_bottom = _margin_bottom;
      st.emboss = _emboss;
      st.font = _font;
      st.reverse_flag = _rv_fl;
      st.enable_focus_move = _enable_focus_move;
      st.toggle_status = _toggle_status;
      st.unique = _unique;
      st.select_reset = _select_reset;
      st.indicator_type = _indicator_type;
      st.indicator_size = _indicator_size;
      st.indicator_on = _indicator_on;
      st.indicator_shadow_thickness = _indicator_shadow_thick;
      st.indicator_size = _indicator_size;
      st.indicator_type = _indicator_type;
      st.indicator_shadow_thickness = _indicator_shadow_thick;
      st.indicator_on = _indicator_on;
      st.indicator_pixmap = _indicator_pixmap;
      st.indicator_color = _indicator_color;

      _ext_draw_proc(&st);
      return WS_NO_ERR;
    }
  }

  WSCstring str;
  if (_press_status == False){
    str.setString( _label_string );
  }else{
    if (_select_string == NULL){
      str.setString( _label_string );
    }else{
      if (_select_string[0] == 0 ){
        str.setString( _label_string );
      }else{
        str.setString( _select_string );
      }
    }
  }
  if (_orientation == WS_VERTICAL) {
    WSGFcreateVerticalString(&str);
  } else {
    str.replaceString("\\n", "\n", 0);
  }

  long err = dev->beginDraw(x, y, w, h, absolute);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }

  WSCbase::update();
  setAbsoluteDraw(False);

  if (_rv_fl == True) {
    if (blinking  != False &&
        blinkfore != False &&
        blinktype != WS_FORE ){
      dev->setForeColor(blinkcolorno);
    } else {
      dev->setForeColor(fgno);
    }
  } else {
    if (blinking  != False &&
        blinkfore != False &&
        blinktype != WS_FORE ){
      dev->setForeColor(backblinkno);
    } else {
      dev->setForeColor(bgno);
    }
  }

  if (_grad_no == 0){
    dev->drawFillRect(0, 0, w, h);
  }else{
    if (_press_status == True  && _indicator_on == False){
      dev->drawGradation(_grad_no,tsno,bgno,bsno,0, 1, w, h,_grad_margin);
    }else{
      dev->drawGradation(_grad_no,tsno,bgno,bsno,0, 0, w, h,_grad_margin);
    }
  }

  short offsetx = 0;
  short left_margin = _margin_left;
  short right_margin = _margin_right;
  short top_margin    = _margin_top;
  short bottom_margin = _margin_bottom;

  if (_indicator_on == True) {
    offsetx = _indicator_size;
  }
  short sx = st + left_margin + offsetx;
  short sy = st + top_margin;
  short sw = 0;
  short sh = 0;
  if ( w > offsetx + st * 2){
    sw = w -offsetx -st * 2;
  }
  if ( sw < left_margin + right_margin ){
    sw = 1;
  }else{
    sw = sw - left_margin - right_margin;
  }

  if ( h > st * 2){
    sh = h - st * 2;
  }

  if (sh < top_margin + bottom_margin){
    sh = 1;
  }else{
    sh = sh - top_margin - bottom_margin;
  }
  WSDimage* image;
  if (blinking  != False &&
      blinktype != WS_BACK &&
      blinkfore != False ){
    if (_blink_pixmap != -1 && twinblink != False){
      image = WSGIappImageSet()->getImage(_blink_pixmap);
      short dy = sy;
      if (_press_status == True  && _indicator_on == False){
        dy++;
      }
      dev->drawImage (sx, dy, sw, sh, image, getAlignment());
    }
  } else {
    if ( _label_pixmap != -1){
      image = WSGIappImageSet()->getImage( _label_pixmap );
      short dy = sy;
      if (_press_status == True  && _indicator_on == False){
        dy++;
      }
      dev->drawImage (sx, dy, sw, sh, image, getAlignment());
    }
  }

//  if (st > 0){
//    char type = WS_SHADOW_OUT;
//    if (_press_status == True  && _indicator_on == False){
//      type = WS_SHADOW_IN;
//    }
//    WSGFdrawBtnShadow(dev, type, st, _fore_color, tsno, bsno,bgno, 0, 0, w, h);
//  }
  if (getSensitive() == False ||
      (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0)){
    if (_emboss != False){
      if (_bl_fl != False &&
        blinkfore != False &&
        _bl_type != WS_BACK &&
        _tw_fl != False) {
        dev->setForeColor(blinkcolorno);
      } else {
        dev->setForeColor(tsno);
      }
      dev->setBackColor(bgno);

      if (blinking  != False &&
          blinktype != WS_BACK &&
          blinkfore != False &&
          twinblink == False){
      }else{
        if (twinblink == False || blinking == False){
          dev->drawString(sx+1, sy+1, sw, sh,
                      &str, _font, getAlignment(), -1, False);
        }
      }
    }else{
      dev->setHatchPattern(8);
    }
  } else {
    dev->setHatchPattern(0);
  }

  if (_indicator_on == True){
     offsetx = _indicator_size;
  }
  if (_rv_fl == True) {
    if (_bl_fl == True &&
        blinkfore == True &&
        _bl_type != WS_BACK &&
        _tw_fl == True){
      dev->setForeColor(_bg_blink_color);
    }else{
      if ( _emboss != False && (getSensitive() == False ||
          (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
        dev->setForeColor(_bs_color);
      } else {
        dev->setForeColor(_back_color);
      }
    }
  } else {
    if (_bl_fl == True &&
        blinkfore == True &&
        _bl_type != WS_BACK &&
        _tw_fl == True){
      dev->setForeColor(_blink_color);
    }else{
      if ( _emboss != False && (getSensitive() == False ||
          (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
         dev->setForeColor(_bs_color);
      }else{
         dev->setForeColor(_fore_color);
      }
    }
  }
  if (sw != 0 && sh != 0){

    if (_bl_fl  != False &&
        _bl_type != WS_BACK &&
        blinkfore != False &&
        _tw_fl == False){
        // 描画しない
    }else{


      if (_press_status == True  && _indicator_on == False){
        dev->drawString(sx ,sy  +1,
                        sw ,sh, &str, _font, getAlignment(), -1, False);
      }else{
        dev->drawString(sx, sy, sw, sh,
                      &str, _font, getAlignment(), -1, False);
      }

      //フォーカスの点線のアンダーラインの描画
      // フォーカス移動可否が可の場合のみ
      if (getFocus() == True && _enable_focus_move == True){
        dev->setLineWidth( 1 );
        dev->setLineDashType( 8 );
        if (w > 4 + st*2 && h > 4 + st*2){
          if (_indicator_on == False){
            if (_press_status == True ){
              dev->drawRect(st+2, st+3, w-st*2-4, h-st*2-4);
            }else{
              dev->drawRect(st+2, st+2, w-st*2-4, h-st*2-4);
            }
          }else{
            WSCushort ww = 0;
            if ( w > offsetx + st * 2 +4 + left_margin/2){
              ww = w -offsetx -st * 2 -4 - left_margin/2;
            }
            if (ww >0 && (long)h-(long)st*2 -4 > 0){
              dev->drawRect(st+left_margin/2+2+_indicator_size, st+2, ww, h -st*2 -4);
            }
          }
        }
      }

    }
  }
  if (_indicator_on == True){
//    char itype = _indicator_type;
    WSCushort isize = _indicator_size;
    short ypos = (h - isize)/2;
    short xpos = st + left_margin /2;
    if (h < isize){
      ypos = 0;
    }

    if (_unique == 0){
      dev->setForeColor(_indicator_color); 
      dev->drawFillRect(xpos, ypos, isize, isize);

      if (_press_status == True ){
        dev->setForeColor(_select_color);
        long iw = isize -st*2;
        WSCpoint pt[6];
        pt[0].x = xpos + _shadow_thick + iw/4;
        pt[0].y = ypos + _shadow_thick + iw/4;
        pt[1].x = xpos + _shadow_thick;
        pt[1].y = ypos + _shadow_thick + iw/2;
        pt[2].x = xpos + isize/2;
        pt[2].y = ypos + isize - _shadow_thick;
        pt[3].x = xpos + isize - _shadow_thick;
        pt[3].y = ypos + _shadow_thick;
        pt[4].x = xpos + isize/2;
        pt[4].y = ypos + isize/2;
        dev->drawFillPoly(pt,5);
      }

      WSGFdrawShadow(dev, WS_SHADOW_IN, _shadow_thick,
                   _fore_color, _ts_color, _bs_color,_back_color,
                   xpos, ypos , isize, isize);
    }else{
      dev->setHatchPattern((char)0);
      dev->setForeColor(_bs_color); 
      dev->drawFillArc(xpos,ypos,isize,isize,60*64,180*64,WS_ARC_PIE);
      dev->setForeColor(_ts_color); 
      dev->drawFillArc(xpos,ypos,isize,isize,240*64,180*64,WS_ARC_PIE);
      dev->setForeColor(_indicator_color); 
      dev->drawFillArc(xpos+_shadow_thick,ypos+_shadow_thick,
                       isize - _shadow_thick*2,
                       isize - _shadow_thick*2,0*64,360*64,WS_ARC_PIE);

      if (_press_status == True ){
        dev->setForeColor(_select_color);
        dev->drawFillArc(xpos+_shadow_thick*2,
                         ypos+_shadow_thick*2,
                         isize - _shadow_thick*4,
                         isize - _shadow_thick*4,0*64,360*64,WS_ARC_PIE);
      }
    }
  }

  dev->endDraw();
  return WS_NO_ERR;

}
void(*WSCvradio::_ext_draw_proc)(void*) = NULL;
WSCstring WSCvradio::_policy_name;

void WSCvradio::onGuiPolicyChange(long policy){
  WSCvlabel::onGuiPolicyChange(policy);
  if (WSGIappDev()->getExtGuiPolicySelected() == False){
    _ext_draw_proc = NULL;
  }else{
    if (!strcmp((char*)_policy_name,(char*)WSGIappDev()->getExtGuiPolicyName())){
    }else{
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->getExtGuiPolicyProc("WSCvradio::draw");
    }
  }
  if (getVisible() != False){
    needUpdate();
    setAbsoluteDraw(True);
    redraw();
  }
}

