//
// 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 <WSCmenuArea.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSCblink.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSDdev.h>
#include <WSDcolor.h>
#include <WSCfontSet.h>
#include <WSDappDev.h>
#include <WSCpulldownMenu.h>
#include <WSCbaseList.h>

WSMFguiClassInitialize(WSCmenuArea, WSCform);
WSMFversion(WSCmenuArea, WSCform);


WSMFpropertyValueChange(WSCmenuArea,WSNshadowType,char,WS_SHADOW_NONE);
WSMFpropertyValueChange(WSCmenuArea,WSNbackColor,short,WS_DF_MENUBACKCOLOR);

WSCmenuArea::WSCmenuArea(WSCbase* base, char* objname):
			WSCform(base, objname){
  _shadow_type = WS_SHADOW_NONE;
  _x = 0;
  _y = 0;
  _w = 1;
  _back_color = WS_DF_MENUBACKCOLOR;
  _w_bak = 0;
  _anchor_left = 0;
  _anchor_right = 0;
  WSGIappObjectList()->addEvent(this,WSEV_GUI_POLICY_CH);

  WSCbase* parent = getParent();
  if (parent != NULL){
    WSCushort st = parent->getProperty(WSNshadowThickness);
    WSCushort width = parent->getProperty(WSNwidth);
    if (_w != width - st*2){
      _w = width - st*2;
    }
    _anchor_left = st;
    _anchor_right = st;
  }
  _anchor_left_use = True;
  _anchor_right_use = True;

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCmenuArea);

    WSMFpropertyValueChangeDef(WSCmenuArea,WSNshadowType,char);
    WSMFpropertyValueChangeDef(WSCmenuArea,WSNbackColor,short);
    WSMFpropertyDelete(WSNshadowThickness);
    WSMFpropertyDelete(WSNshadowType);
    WSMFpropertyVisibleOff(WSNanchorLeftFlag);
    WSMFpropertyVisibleOff(WSNanchorLeft);
    WSMFpropertyVisibleOff(WSNanchorRightFlag);
    WSMFpropertyVisibleOff(WSNanchorRight);
    WSMFpropertyVisibleOff(WSNanchorTopFlag);
    WSMFpropertyVisibleOff(WSNanchorTop);
    WSMFpropertyVisibleOff(WSNanchorBottomFlag);
    WSMFpropertyVisibleOff(WSNanchorBottom);
  WSMFpropertyCreateEnd
}
WSCmenuArea::~WSCmenuArea(){
    WSGIappObjectList()->delEvent(this,WSEV_GUI_POLICY_CH);
}
void WSCmenuArea::setWorkWSNx(short val){
#if 0
  WSCbase* parent = getParent();
  if (parent != NULL){
    WSCushort st = parent->getProperty(WSNshadowThickness);
    if (_x != st){
      _x = st;
      WSCform::setWorkWSNx(st);
    }
  }
#else
  WSCform::setWorkWSNx(val);
#endif
}
void WSCmenuArea::setWorkWSNy(short val){
#if 0
  WSCbase* parent = getParent();
  if (parent != NULL){
    WSCushort st = parent->getProperty(WSNshadowThickness);
    if (_y != st){
      _y = st;
      WSCform::setWorkWSNy(st);
    }
  }
#else
  WSCform::setWorkWSNy(val);
#endif
}
void WSCmenuArea::setWorkWSNwidth(WSCushort){
  WSCbase* parent = getParent();
  if (parent != NULL){
    WSCushort st = 0;
    if (parent->existProperty(WSNshadowThickness) != False){
      st = parent->getProperty(WSNshadowThickness);
    }
    WSCushort width = parent->getProperty(WSNwidth);
    WSCushort w = width - st*2;
    if (_w_bak != w){
      if (_initialized != False && _dev != NULL){
        WSCform::setWorkWSNwidth(w);
        _w_bak = _w;
      }
    }
  }
}

long WSCmenuArea::initialize(){
  long ret = WSCform::initialize();
  WSCbase* parent = getParent();
  if (parent != NULL){
    if (parent->cast("WSCvertForm") == NULL){
      long val = (long)parent->getUserData("menuarea-resize-work");
      if (val == 0){
        parent->setUserData("menuarea-resize-work",(void*)1);
        WSCprocedure* resize_op = new WSCprocedure("resizeop",WSEV_RESIZE);
        resize_op->setFunction(_resize_work,"_resize_work");
        resize_op->setInternal(True);
        parent->addProcedure(resize_op);
//        parent->execProcedure(WSEV_RESIZE);
      }
      _resize_work(parent);
    }
  }
  return ret;
}
void WSCmenuArea::_resize_work(WSCbase* form){
  WSClistData children = form->getChildren();

  WSCulong pwidth = form->getProperty(WSNwidth);
//  WSCulong pheight = form->getProperty(WSNheight);
  WSCulong pst = form->getProperty(WSNshadowThickness);
  WSClistData achildren;

  long i;
  long num = children.getNum();
  for(i=0; i<num; i++){
    WSCbase* child = (WSCbase*)children[i];
    if (child->getVisible() == False){
      continue;
    }
    WSCmenuArea* area;
    if ((area = (WSCmenuArea*)child->cast("WSCmenuArea")) == NULL){
      continue;
    }

    long k;
    long knum = achildren.getNum();
    long added = 0;
    for(k=0; k<knum; k++){
      WSCbase* item = (WSCbase*)achildren[k];
      long y1 = item->getProperty(WSNy);
      long y2 = child->getProperty(WSNy);
      if (y1 > y2){
        achildren.add((void*)child,k);
        added = 1;
        break;
      }
    }
    if (added == 0){
      achildren.add((void*)child);
    }
  }
  long ypos = pst;
  num = achildren.getNum();
  for(i=0; i<num; i++){
    WSCbase* child = (WSCbase*)achildren[i];
//    child->setProperty(WSNx,pst);
    child->setProperty(WSNy,ypos);
//    child->setProperty(WSNwidth,(pwidth - pst*2));
    WSCulong h = child->getProperty(WSNheight);
    ypos += h;
    WSClistData mchildren = child->getChildren();
    long xpos = 0;
    long j;
    long mnum = mchildren.getNum();
    WSClistData mchildren2;
    for(j=0; j<mnum; j++){
      WSCbase* mchild = (WSCbase*)mchildren[j];
      if (mchild->getVisible() == False){
        continue;
      }
      if (mchild->getInternalObject() != False){
        continue;
      }
//      if (mchild->cast("WSCpulldownMenu") == NULL){
//        continue;
//      }

      if (mchild->cast("WSCmenuArea") != NULL){
        continue;
      }
      if (mchild->getObjectType() & WS_TYPE_WINDOW){
        continue;
      }
      long k;
      long knum = mchildren2.getNum();
      long added = 0;
      for(k=0; k<knum; k++){
        WSCbase* item = (WSCbase*)mchildren2[k];
        long x1 = item->getProperty(WSNx);
        long x2 = mchild->getProperty(WSNx);
        if (x1 > x2){
          mchildren2.add((void*)mchild,k);
          added = 1;
          break;
        }
      }
      if (added == 0){
        mchildren2.add((void*)mchild);
      }
    }

    mnum = mchildren2.getNum();
    for(j=0; j<mnum; j++){
      WSCbase* mchild = (WSCbase*)mchildren2[j];
      mchild->setProperty(WSNx,xpos);
      mchild->setProperty(WSNy,0);
      long h = child->getProperty(WSNheight);
      if (h >2){
        h -= 2;
      }else{
        h = 1;
      }
      mchild->setProperty(WSNheight,h);
      xpos += (WSCulong)mchild->getProperty(WSNwidth);
    }
  }
}
long WSCmenuArea::draw(){
  if (_no_refresh != False){
    WSCbase::update();
    setAbsoluteDraw(False);
    return WS_NO_ERR;
  }
  if (getVisible() == False){
    return WS_NO_ERR;
  }
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }
  WSCbool absolute = getAbsoluteDraw();
  if (absolute == False  ){
    if ( dev->isExposed(0,0,_w,_h) == False ){
      return WS_NO_ERR;
    }
  }
  if (WSGIappDev()->getExtGuiPolicySelected() != False){
    if (_ext_draw_proc == NULL){
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->
                               getExtGuiPolicyProc("WSCmenuArea::draw");
    }
    if (_ext_draw_proc != NULL){
      WSCmenuArea_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.shadow_type = _shadow_type;
      st.fore_color = _fore_color;
      st.back_color = _back_color;
      st.top_shadow_color = _ts_color;
      st.bottom_shadow_color = _bs_color;
      st.back_pixmap = _bp_color;
      st.gradation = _grad_no;
      st.gradation_margin = _grad_margin;
      _ext_draw_proc(&st);

      if (getDotMode() != False){
        WSCbase* parent = getParent();
        if (parent->cast("WSCvertForm") == NULL){
          WSCulong pwidth = parent->getProperty(WSNwidth);
          WSCulong pst = parent->getProperty(WSNshadowThickness);
          if (_w != pwidth - pst*2){
            parent->setGeometryChanged(True);
            parent->needUpdate();
          }
          _resize_work(parent);
        }
      }
      return WS_NO_ERR;
    }
  }

  long err = dev->beginDraw(0,0,_w,_h,absolute);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }
  short ex = 0;
  short ey = 0;
  WSCushort ew = _w;
  WSCushort eh = _h;
  if (absolute == False){
    dev->getExposedArea(&ex,&ey,&ew,&eh);
  }
  WSCbase::update();
  setAbsoluteDraw(False);
  if (_bp_color == -1){
    if (_grad_no == 0){
      dev->setForeColor(_back_color);
      dev->drawFillRect(0,0,_w,_h);
    }else{
      dev->drawGradation(_grad_no,_ts_color,_back_color,_bs_color,0,0,_w,_h,_grad_margin);
    }
  }
  if (getDotMode() != False){
    dev->setForeColor(_fore_color);
    long i,j;
    for(i=0; i<_w; i+=10){
      for(j=0; j<_h; j+=10){
        if (ex < i && i < ex+ ew &&
            ey < j && j < ey+ eh ){
          dev->drawFillRect(i,j,1,1);
        }
      }
    }
  }
  if (_shadow_type != WS_SHADOW_NONE){
    WSGFdrawShadow(dev,_shadow_type,_shadow_thick,_fore_color,_ts_color,_bs_color,_back_color,0,0,_w,_h);
  }else{
//    WSGFdrawShadow(dev,WS_SHADOW_EIN,2,_fore_color,_ts_color,_bs_color,_back_color,-2,-2,_w+4,_h+2);
    dev->setLineWidth(0);
    dev->setForeColor(_bs_color);
    dev->drawLine(0,_h-2,_w,_h-2);
    dev->setForeColor(_ts_color);
    dev->drawLine(0,_h-1,_w,_h-1);
  }
  dev->endDraw();

  if (getDotMode() != False){
    WSCbase* parent = getParent();
    if (parent->cast("WSCvertForm") == NULL){
      WSCulong pwidth = parent->getProperty(WSNwidth);
      WSCulong pst = parent->getProperty(WSNshadowThickness);
      if (_w != pwidth - pst*2){
        parent->setGeometryChanged(True);
        parent->needUpdate();
      }
      _resize_work(parent);
    }
  }

  return WS_NO_ERR;
}
void(*WSCmenuArea::_ext_draw_proc)(void*) = NULL;
WSCstring WSCmenuArea::_policy_name;

void WSCmenuArea::onGuiPolicyChange(long policy){
  WSCbase::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("WSCmenuArea::draw");
    }
  }
  needUpdate();
  setAbsoluteDraw(True);
  redraw();
}

