//
// 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 <WSCscrFrame.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSDdev.h>
#include <WSDmouse.h>

WSMFguiClassInitialize(WSCscrFrame,WSCform);
WSMFversion(WSCscrFrame,WSCform);
WSMFdefineUseDevice(WSCscrFrame,scrFrameDev)

WSCscrFrame::WSCscrFrame(WSCbase* base,char* objname):
                WSCform(base,objname){

  _title_height = 0;
  _s_w = 0;
  _s_h = 0;
  _w_w = 1000;
  _w_h = 1000;
  _no_scroll = False;

  WSMFpropertyCreateStart
      WSMFparentCheckVerSrc(WSCscrFrame);

      WSMFpropertyCreate(WSNtitleHeight,  WSCushort,_title_height,WSStitleHeight);
      WSMFpropertyCreate(WSNhbarValue,    WSCushort,_s_w,WSShbarValue);
      WSMFpropertyCreate(WSNvbarValue,    WSCushort,_s_h,WSSvbarValue);
      WSMFpropertyCreate(WSNworkWidth,    WSCushort,_w_w,WSSworkWidth);
      WSMFpropertyCreate(WSNworkHeight,   WSCushort,_w_h,WSSworkHeight);
  WSMFpropertyCreateEnd

}

WSMFproperty( WSCscrFrame, WSNtitleHeight,  WSCushort, _title_height ,0);
WSMFproperty( WSCscrFrame, WSNhbarValue,    WSCushort, _s_w    ,0);
WSMFproperty( WSCscrFrame, WSNvbarValue,    WSCushort, _s_h    ,0);
WSMFproperty( WSCscrFrame, WSNworkWidth,    WSCushort, _w_w    ,1000);
WSMFproperty( WSCscrFrame, WSNworkHeight,   WSCushort, _w_h    ,1000);

void WSCscrFrame::setWorkWSNhbarValue(WSCushort data){
  if (data + _w > _w_w ){
    if (_w_w < _w){
      data = 0;
      _s_w = 0;
    }else{
      data = _w_w - _w;
      _s_w = _w_w - _w;
    }
  }
  WSDdev* dev = getowndev();
  if (dev != NULL){
    if (_no_scroll == False){
      dev->setValue(WSDEV_WORK_X,&data);
    }else{
      WSCushort val = 0;
      dev->setValue(WSDEV_WORK_X,&val);
    }
  }
}

void WSCscrFrame::getWorkWSNhbarValue(WSCushort*){
}

void WSCscrFrame::setWorkWSNvbarValue(WSCushort data){
  if (data + _h > _w_h ){
    if (_w_h < _h){
      data = 0;
      _s_h = 0;
    }else{
      data = _w_h - _h;
      _s_h = _w_h - _h;
    }
  }
  WSDdev* dev = getowndev();
  if (dev != NULL){
    if (_no_scroll == False){
      dev->setValue(WSDEV_WORK_Y,&data);
    }else{
      WSCushort val = 0;
      dev->setValue(WSDEV_WORK_Y,&val);
    }
  }
}

void WSCscrFrame::getWorkWSNvbarValue(WSCushort*){
}

void WSCscrFrame::setWorkWSNworkWidth(WSCushort data){
  WSDdev* dev = getowndev();
  if (dev != NULL){
    _w_w = data;
    if (_s_w + _w > _w_w ){
      if (_w_w < _w){
        _s_w = 0;
      }else{
        _s_w = _w_w - _w;
      }
      if (_no_scroll == False){
        _dev->setValue(WSDEV_WORK_X,     &_s_w);
      }else{
        WSCushort val = 0;
        _dev->setValue(WSDEV_WORK_X,     &val);
      }
    }
    if (_no_scroll == False){
      _dev->setValue(WSDEV_WORK_WIDTH, &_w_w);
    }else{
      _dev->setValue(WSDEV_WORK_WIDTH, &_w);
    }
  }
}

void WSCscrFrame::getWorkWSNworkWidth(WSCushort*){
}

void WSCscrFrame::setWorkWSNworkHeight(WSCushort data){
  WSDdev* dev = getowndev();
  if (dev != NULL){
    _w_h = data;
    if (_s_h + _h > _w_h ){
      if (_w_h < _h){
        _s_h = 0;
      }else{
        _s_h = _w_h - _h;
        if (_no_scroll == False){
          _dev->setValue(WSDEV_WORK_Y,     &_s_h);
        }else{
          WSCushort val = 0;
          _dev->setValue(WSDEV_WORK_Y,     &val);
        }
      }
    }
//printf("WSCscrFrame::setWorkWSNworkHeight %s %d\n",getInstanceName(),data);
    if (_no_scroll == False){
      _dev->setValue(WSDEV_WORK_HEIGHT,&_w_h);
    }else{
      _dev->setValue(WSDEV_WORK_HEIGHT,&_h);
    }
  }
}

void WSCscrFrame::getWorkWSNworkHeight(WSCushort*){
}

void WSCscrFrame::setWorkWSNtitleHeight(WSCushort data){
  WSDdev* dev = getowndev();
  if (dev != NULL){
    dev->setValue(WSDEV_TITLE_HEIGHT,&data);
  }
}

void WSCscrFrame::getWorkWSNtitleHeight(WSCushort*){
}

long WSCscrFrame::_device_initialize(){
  WSCform::_device_initialize();
  if (_dev != NULL){
    if (_no_scroll == False){
      _dev->setValue(WSDEV_WORK_WIDTH, &_w_w);
      _dev->setValue(WSDEV_WORK_HEIGHT,&_w_h);
      _dev->setValue(WSDEV_WORK_X,     &_s_w);
      _dev->setValue(WSDEV_WORK_Y,     &_s_h);
    }else{
      WSCushort val =0;
      _dev->setValue(WSDEV_WORK_WIDTH, &_w);
      _dev->setValue(WSDEV_WORK_HEIGHT,&_h);
      _dev->setValue(WSDEV_WORK_X,     &val);
      _dev->setValue(WSDEV_WORK_Y,     &val);
    }
    _dev->setEnableEventBit(WSEV_MOUSE_PRESS_BIT | WSEV_MOUSE_RELEASE_BIT);
  }
  return WS_NO_ERR;
}


long WSCscrFrame::clear(){
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }

  if (getVisible() == False){
    return WS_ERR;
  }

  long err = dev->beginDraw(0,0,_w_w,_w_h,True);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }

  dev->clearArea(0,0,_w_w,_w_h,False);
  dev->endDraw();

  return WS_NO_ERR;
}


long WSCscrFrame::redraw(){
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }

  if (getVisible() == False){
    return WS_ERR;
  }

  long err = dev->beginDraw(0,0,_w_w,_w_h,True);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }
  dev->clearArea(0,0,_w_w,_w_h,True);
  dev->endDraw();

  return WS_NO_ERR;
}

long WSCscrFrame::cdraw(){
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }
  if (getVisible() == False){
    return WS_ERR;
  }

  WSCrect area;
  area.x = _s_w;
  area.y = _s_h;
  area.width = _w;
  area.height = _h;

  WSCbool flbk;
  dev->getValue(WSDEV_EXPOSE_SEQUENCE,&flbk);
  WSCbool fl = True;
  dev->setValue(WSDEV_EXPOSE_SEQUENCE,&fl);

  short bx,by;
  WSCushort bw,bh;
  dev->getExposedArea(&bx,&by,&bw,&bh);
  dev->setExposedArea(_s_w,_s_h,_w,_h);
  setAbsoluteDraw(True);
  dev->execEvent(WSEV_EXPOSE,&area);
  dev->setExposedArea(bx,by,bw,bh);
  dev->setValue(WSDEV_EXPOSE_SEQUENCE,&fl);

  return WS_NO_ERR;
}

long WSCscrFrame::draw(){
  if (getVisible() == False){
    return WS_NO_ERR;
  }
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }

  WSCushort width = _w_w;
  WSCushort height = _w_h;

  WSCbool absolute = getAbsoluteDraw(); 
  if (absolute == False && dev->isExposed(0,0,width,height) == False){
    return WS_NO_ERR;
  }

  short ex = 0;
  short ey = 0;
  WSCushort ew = width;
  WSCushort eh = height;
  if (absolute == False){
    dev->getExposedArea(&ex,&ey,&ew,&eh);
//WSMFtrace("WSCscrFrame::draw()    ex,ey,ew,eh~%d,%d,%d,%d\n",ex,ey,ew,eh);
  }
  WSCbase::update();
  setAbsoluteDraw(False);

  long err = dev->beginDraw(0,0,width,height,absolute);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }
  long ex1,ey1;
  WSCulong ew1,eh1;
  WSGFandArea(_s_w,_s_h,_w,_h,ex,ey,ew,eh,&ex1,&ey1,&ew1,&eh1);

  dev->setForeColor(_back_color);
  dev->drawFillRect(ex1,ey1,ew1,eh1);
  if (getDotMode() == True){
    dev->setForeColor(_fore_color);
    long i,j;
    for(i=0; i<width; i+=10){
      for(j=0; j<height; j+=10){
        if (ex1 < i && i < ex1 + (long)ew1 &&
            ey1 < j && j < ey1 + (long)eh1 ){
          dev->drawFillRect(i,j,1,1);
        }
      }
    }
  }
  dev->endDraw();
  return WS_NO_ERR;
}

void WSCscrFrame::update(){
  if (_no_scroll != False){
    _dev->setValue(WSDEV_WORK_WIDTH, &_w_w);
    _dev->setValue(WSDEV_WORK_HEIGHT,&_w_h);
  }
  if (isNeedUpdate() != False){
    WSCbase::update();
  }
}

void WSCscrFrame::onParentVisibleChange(WSCbool fl){
  WSCform::onParentVisibleChange(fl);
  if (fl != False && _dev != NULL){
    if (_no_scroll == False){
      _dev->setValue(WSDEV_WORK_X,     &_s_w);
      _dev->setValue(WSDEV_WORK_Y,     &_s_h);
    }else{
      WSCushort val =0;
      _dev->setValue(WSDEV_WORK_X,     &val);
      _dev->setValue(WSDEV_WORK_Y,     &val);
    }
  }
}

void WSCscrFrame::onVisibleChange(WSCbool fl){
  WSCform::onVisibleChange(fl);
  if (fl != False && _dev != NULL){
    _device_initialize();
//    _dev->setValue(WSDEV_WORK_X,     &_s_w);
//    _dev->setValue(WSDEV_WORK_Y,     &_s_h);
  }
}

void WSCscrFrame::setHbarValue(WSCushort val){
  if (_s_w != val){
    if (val + _w > _w_w ){
      if (_w_w < _w){
        _s_w = 0;
      }else{
        _s_w = _w_w - _w;
      }
    }else{
      _s_w = val;
    }
    if (_dev != NULL){
      if (_no_scroll == False){
        _dev->setValue(WSDEV_WORK_X,     &_s_w);
      }else{
        WSCushort val =0;
        _dev->setValue(WSDEV_WORK_X,     &val);
      }
    }
  }
}

void WSCscrFrame::setVbarValue(WSCushort val){
  if (_s_h != val){
    if (val + _h > _w_h ){
      if (_w_h < _h){
        _s_h = 0;
      }else{
        _s_h = _w_h - _h;
      }
    }else{
      _s_h = val;
    }
    if (_dev != NULL){
      if (_no_scroll == False){
        _dev->setValue(WSDEV_WORK_Y,     &_s_h);
      }else{
        WSCushort val =0;
        _dev->setValue(WSDEV_WORK_Y,     &val);
      }
    }
  }
}
void WSCscrFrame::onMousePress(WSCpoint* pt){
  WSCbase* parent = getParent();
  if (parent->cast("WSCscrForm")){
    WSGIappMouse()->setMouseFocusClient(parent);
  }
  WSCbase::onMousePress(pt);
}
void  WSCscrFrame::_set_no_scroll(WSCbool fl){
  _no_scroll = fl;
  if (fl != False){
    if (_dev != NULL){
      WSCushort val =0;
      _dev->setValue(WSDEV_WORK_WIDTH, &_w);
      _dev->setValue(WSDEV_WORK_HEIGHT,&_h);
      _dev->setValue(WSDEV_WORK_X,     &val);
      _dev->setValue(WSDEV_WORK_Y,     &val);
    }
  }else{
    if (_dev != NULL){
      _dev->setValue(WSDEV_WORK_WIDTH, &_w_w);
      _dev->setValue(WSDEV_WORK_HEIGHT,&_w_h);
      _dev->setValue(WSDEV_WORK_X,     &_s_w);
      _dev->setValue(WSDEV_WORK_Y,     &_s_h);
    }
  }
}
