//
// 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 <WSCvklabel.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSDdev.h>
#include <WSCimageSet.h>
#include <WSDkeyboard.h>
#include <WSDtimer.h>
#include <WSCfontSet.h>
#include <WSClist.h>
#include <WSDmouse.h>
#include <WSCpopupMenu.h>
#include <WSClist.h>

WSMFguiClassInitialize(WSCvklabel,WSCvlabel);
WSMFversion(WSCvklabel,WSCvlabel);

WSCvklabel::WSCvklabel(WSCbase* base,char* objname):
                WSCvlabel(base,objname){

  _register_focus_move();
  _select_color = 0;
  _select_fore_color = 0;
  _select_color_work = 0;
  _select_fore_color_work = 0;
  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCvklabel);
    WSMFpropertyCreate(WSNselectColor, short, _select_color_work,WSSselectColor );
    WSMFpropertyCreate(WSNselectForeColor, short, _select_fore_color_work,WSSselectForeColor );

    WSMFaddTrigger(WSEV_KEY_PRESS   );
    WSMFaddTrigger(WSEV_KEY_RELEASE );
    WSMFaddTrigger(WSEV_FOCUS_CH    );
    WSMFaddTrigger(WSEV_ACTIVATE    );

  WSMFpropertyCreateEnd
}
WSMFproperty(WSCvklabel,WSNselectColor, short, _select_color_work ,WS_DF_MENUSELECTCOLOR);
WSMFproperty(WSCvklabel,WSNselectForeColor, short, _select_fore_color_work ,WS_DF_MENUSELECTFORECOLOR);
void WSCvklabel::setWorkWSNselectColor(short ){
  _select_color = _select_color_work;
}
void WSCvklabel::getWorkWSNselectColor(short* ){}
void WSCvklabel::setWorkWSNselectForeColor(short ){
  _select_fore_color = _select_fore_color_work;
}
void WSCvklabel::getWorkWSNselectForeColor(short* ){}

WSCvklabel::~WSCvklabel(){
//  if (getFocus() != False){
//    WSGIappKeyboard()->resetFocusInputWorkProc();
//  }
}

long WSCvklabel::_device_initialize(){
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }
  dev->setEnableEvent(WSEV_MOUSE_PRESS);

  WSCvlabel::_device_initialize();
  return WS_NO_ERR;
}

long WSCvklabel::draw(){
dbprintf("WSCvklabel::draw %s:%d strart this=0x%x %s\n",__FILE__,__LINE__,this,getInstanceName());
  if (getVisible() == False){
dbprintf("WSCvklabel::draw %s:%d done1 vis=False %s\n",__FILE__,__LINE__,getInstanceName());
    return WS_NO_ERR;
  }
  if (_parent != NULL){
    void* ptr = _parent->cast("WSClist");
dbprintf("WSCvklabel::draw %s:%d %s ptr=0x%x\n",__FILE__,__LINE__,getInstanceName(),ptr);
    if (ptr != NULL){
      WSCuchar fl;
      _parent->getPropertyV(WSNtype,&fl);
      set_vk_draw(fl);

      WSCbool fl2;
      _parent->getPropertyV(WSNuseIcon,&fl2);
      if (fl2 == False){
        set_use_icon(False);
      }else{
        set_use_icon(True);
      }
      if (get_vk_draw() == WS_VERBOSE){
        set_bar_pos(_parent->getProperty(WSNbarValue));
      }
    }
  }
  long ret = WSCvlabel::draw();
  set_vk_draw(WS_NORMAL);
  set_use_icon(False);
  set_bar_pos("");
dbprintf("WSCvklabel::draw %s:%d done2 this=0x%x %s\n",__FILE__,__LINE__,this,getInstanceName());
  return ret;
}

void WSCvklabel::_key_handler(void* ptr,WSDkeyboard* keyboard,WSCbool fl){
  WSCvklabel* obj = (WSCvklabel*)ptr;
  if (obj->getVisible() == False){
    return;
  }
  if (obj->getSensitive() == False){
    return;
  }
  if (obj->_parent != NULL){
    WSClist* ptr = (WSClist*)obj->_parent->cast("WSClist");
    if (ptr != NULL){
      if (fl != False){
        ptr->onKey(keyboard,True);
        ptr->execProcedure(WSEV_KEY_PRESS);
      }else{
        ptr->onKey(keyboard,False);
        ptr->execProcedure(WSEV_KEY_RELEASE);
      }
    }
  }
  if (fl != False){
    obj->onKey(keyboard,True);
    obj->execProcedure(WSEV_KEY_PRESS);
  }else{
    obj->onKey(keyboard,False);
    obj->execProcedure(WSEV_KEY_RELEASE);
  }
}

void WSCvklabel::onKey(WSDkeyboard* kb,WSCbool fl){
  if (fl == False){
    return;
  }
  if (getParent() != NULL){
    WSClist* list = (WSClist*)getParent()->cast("WSClist");
    if (list != NULL){
      WSCbool mselect = list->getProperty(WSNmultiSelect);
      WSCbool with_shift = kb->withShift();
      WSCulong key =  kb->getKey();
      if (key != WSK_Down &&
          key != WSK_Up ){
        return;
      }
      long spos = list->getSelectedPos();
      if (spos < 0){
        return;
      }
      if (mselect ==  False){
        if (key == WSK_Down){
          long num = list->getNum();
          if (spos + 1 < num){
            list->setSelectPos(spos+1);
          }
        }else
        if (key == WSK_Up){
          spos--;
          if (spos <0){
            spos =0;
          }
          list->setSelectPos(spos);
        }
      }else{
        if (with_shift == False){
          spos = (long)list->getVariantData("mselect-pos2");
          WSCbool rev = list->getProperty(WSNreverseSelect);
          if (rev != False){
            list->setProperty(WSNreverseSelect,False);
          }
          list->setProperty(WSNmultiSelect,False);
          if (key == WSK_Down){
            long num = list->getNum();
            if (spos + 1 < num){
              spos++;
            }
          }else
          if (key == WSK_Up){
            if (spos >0){
              spos--;
            }
          }
          list->setSelectPos(spos);
          list->setVariantData("mselect-pos1",spos);
          list->setVariantData("mselect-pos2",spos);
          list->setProperty(WSNmultiSelect,True);
          if (rev != False){
            list->setProperty(WSNreverseSelect,True);
          }
        }else{
          long spos1 = list->getVariantData("mselect-pos1");
          long spos2 = list->getVariantData("mselect-pos2");
          long num = list->getNum();
          if (key == WSK_Down){
            if (spos2 + 1 < num){
              list->setVariantData("mselect-pos2",spos2+1);
            }
          }else
          if (key == WSK_Up){
            if (spos2 > 0){
              list->setVariantData("mselect-pos2",spos2-1);
            }
          }
          spos2 = list->getVariantData("mselect-pos2");
          long i;
          for(i=0; i<num; i++){
            if (spos1 < spos2){
              if (spos1 <= i && i <= spos2){
                list->setSelected(i,True);
              }else{
                list->setSelected(i,False);
              }
            }else{
              if (spos2 <= i && i <= spos1){
                list->setSelected(i,True);
              }else{
                list->setSelected(i,False);
              }
            }
          }
        }
      }
    }
  }
}

void WSCvklabel::onMousePress(WSCpoint* point){
//printf("WSCvklabel::onMousePress %s parent=%s\n",getInstanceName(),getParent()->getInstanceName());
  WSCvlabel::onMousePress(point);
  if ( point->x < 0 || _w < point->x  &&
       point->y < 0 || _h < point->y ){
    return;
  }
  if ((WSGIappMouse()->getStatus() & WS_MOUSE_BTN3)){
    if (_parent != NULL){
      WSClist* ptr = (WSClist*)_parent->cast("WSClist");
      if (ptr != NULL){
        long i;
        WSClistData* list = ptr->getLabels();
        long num = list->getNum();
        for(i=0; i<num; i++){
          WSCbase* lb = (WSCbase*)list->getData(i);
          WSCvlabel* vklb = (WSCvklabel*)lb->cast("WSCvklabel");
          if (this == vklb){
            ptr->setPreSelectPos(i);
            break;
          }
        }
      }
    }
    return;
  }
  if (!(WSGIappMouse()->getStatus() & WS_MOUSE_BTN1)){
    return;
  }
  WSCpopupMenu* obj = (WSCpopupMenu*)getUserData("PM-SERVER");
  if (obj != NULL && obj->getVisible() != False){
//printf("return2...\n");
    return;
  } 
  if (_parent != NULL){
    WSClist* ptr = (WSClist*)_parent->cast("WSClist");
    if (ptr != NULL){
      WSCuchar val;
      _parent->getPropertyV(WSNtype,&val);
      long indent = (long)getUserData(WS_LIST_INDENT_LEVEL);
      if (val == WS_TREE &&
          ((long)_h - (long)_shadow_thick*2) * indent < point->x &&
           point->x < (long)_h + ((long)_h - (long)_shadow_thick*2)*indent &&
           0 < point->y && point->y < _h ){
        long value = (long)getUserData(WS_LIST_TREE_OPEN);
        if (value == 0){
          setUserData(WS_LIST_TREE_OPEN,(void*)1);
        }else{
          setUserData(WS_LIST_TREE_OPEN,(void*)0);
        }
        setUserData(WS_LIST_TREE_OPEN_CH,(void*)1);
        ptr->updateList();
//        WSCuchar val = ptr->getProperty(WSNpixmapStyle);
        redraw();
        ptr->cdraw();
      }else{
        long i;
        WSClistData* list = ptr->getLabels();
        long num = list->getNum();
        WSCbool rev = ptr->getProperty(WSNreverseSelect);
        long spos = ptr->getSelectedPos();
        for(i=0; i<num; i++){
          WSCbase* lb = (WSCbase*)list->getData(i);
          WSCvlabel* vklb = (WSCvklabel*)lb->cast("WSCvklabel");
          if (this == vklb){
            if (i != spos || rev != False){
              WSCbool mselect = ptr->getProperty(WSNmultiSelect);
              WSCulong status = WSGIappMouse()->getMouseStatus();
              if (mselect != False &&
                  (status & WS_MOUSE_SHIFT) == False &&
                  (status & WS_MOUSE_CONTROL) == False){
                ptr->setProperty(WSNmultiSelect,False);
              }
              if (mselect != False &&
                  (status & WS_MOUSE_SHIFT) != False){
                ptr->setVariantData("mselect-pos2",i);
                long spos1 = ptr->getVariantData("mselect-pos1");
                long spos2 = i;
                long j;
                for(j=0; j<num; j++){
                  if (spos1 < spos2){
                    if (spos1 <= j && j <= spos2){
                      ptr->setSelected(j,True);
                    }else{
                      ptr->setSelected(j,False);
                    }
                  }else{
                    if (spos2 <= j && j <= spos1){
                      ptr->setSelected(j,True);
                    }else{
                      ptr->setSelected(j,False);
                    }
                  }
                }
                ptr->WSCbase::update();
                ptr->setVariantData("mselect-pos1",spos1);
                ptr->setVariantData("mselect-pos2",spos2);
              }else{
                ptr->setSelectPos(i);
                ptr->WSCbase::update();
                ptr->setVariantData("mselect-pos1",i);
                ptr->setVariantData("mselect-pos2",i);
              }
              if (mselect != False &&
                  (status & WS_MOUSE_SHIFT) == False &&
                  (status & WS_MOUSE_CONTROL) == False){
                ptr->setProperty(WSNmultiSelect,True);
              }
            }
//            if (i != spos || rev != False){
//              ptr->cdraw();
//            }
            break;
          }
        }
        onActivate();
      }

    }
  }
  setFocus(True);
}
void WSCvklabel::onMouseDoubleClick(WSCpoint* point){
  WSCvlabel::onMouseDoubleClick(point);
  if ( point->x < 0 || _w < point->x  &&
       point->y < 0 || _h < point->y ){
    return;
  }
  if ((WSGIappMouse()->getStatus() & WS_MOUSE_BTN1)){
    if (_parent != NULL){
      WSClist* ptr = (WSClist*)_parent->cast("WSClist");
      if (ptr != NULL){
        long i;
        WSClistData* list = ptr->getLabels();
        long num = list->getNum();
        for(i=0; i<num; i++){
          WSCbase* lb = (WSCbase*)list->getData(i);
          WSCvlabel* vklb = (WSCvklabel*)lb->cast("WSCvklabel");
          if (this == vklb){
            ptr->onItemDoubleClicked();
            break;
          }
        }
      }
    }
    return;
  }
}
void WSCvklabel::onActivate(){
//  execEventProc(WSEV_ACTIVATE,NULL);
  execProcedure(WSEV_ACTIVATE);
}
void WSCvklabel::onFocusChange(WSCbool fl){
  if (getSensitive() == False && fl != False){
    return;
  }
  if (getParent() != NULL && getParent()->cast("WSClist")){
    WSClist* list = (WSClist*)getParent()->cast("WSClist");

    WSCbool mselect = list->getProperty(WSNmultiSelect);
    WSCulong status = WSGIappMouse()->getMouseStatus();
    if (mselect != False &&
       (status & WS_MOUSE_SHIFT) != False){
      //keep mselect-pos data..
    }else{
      long spos = list->getSelectedPos();
      list->setVariantData("mselect-pos1",spos);
      list->setVariantData("mselect-pos2",spos);
    }
  }

  if (fl != False){
    WSGIappKeyboard()->setFocusInputWorkProc(_key_handler,NULL,this);
  }
}
