//===============================================================
// vlistc.cxx   - ListCmd - Windows
//
// Copyright (C) 1995,1996,1997,1998  Bruce E. Wampler
//
// This file is part of the V C++ GUI Framework, and is covered
// under the terms of the GNU Library General Public License,
// Version 2. This library has NO WARRANTY. See the source file
// vapp.cxx for more complete information about license terms.
//===============================================================
#include <v/vos2.h>           // for OS/2 stuff
#include <v/vlistc.h>   // our definitions
#include <v/vcmdprnt.h> // a command parent
#include <v/vapp.h>

//=================>>> vListCmd::vListCmd <<<=======================
  vListCmd::vListCmd(vCmdParent* dp, CommandObject* dc) :
	    vCmd(dp, dc)
  {
    _maxWidth = 10;
    SysDebug(Constructor,"vListCmd::vListCmd() constructor\n")

    CopyToLocal();                      // Make local copies of CmdObject

    // First, setup the list
    _listRows = 8;
    if (dlgCmd->attrs & CA_Size)	// Size specified
    {
      if (dlgCmd->size > 0 && dlgCmd->size <= 32)
        _listRows = dlgCmd->size;
    }

    SetupList();

    _maxWidth = (dlgCmd->attrs & CA_Large) ? (_maxWidth * 3)/2 : _maxWidth;

    long style = (_parentWin->_dialogType != aCmdBar)
		 ? WS_TABSTOP | WS_GROUP
		 : WS_GROUP;

    if (!(dlgCmd->attrs & CA_Hidden))   // Check for Hidden
    {
      style |= WS_VISIBLE;
      _isVisible = 1;
    }
    else
      _isVisible = 0;

    style |= LS_NOADJUSTPOS;

    _w = _maxWidth*4+4;                // set my width

    if ((dlgCmd->attrs & CA_ListWidth) && dlgCmd->retVal > _w)
      _w = dlgCmd->retVal; 		// CA_ListWidth V 1.18 BEW

//    _h = 54;                         // default height (8 rows)
    _h = LONG( (LabelHeight() * _listRows) );  // default height (listRows * 6 each row)

    _parentWin->SetPosition(_x, _y, _w, _h, dlgCmd->cFrame, dlgCmd->cRightOf,
	 dlgCmd->cBelow);

    _y += 1;

    _CtrlOffset = _parentWin->AddDlgControl(_x, _y, _w, _h, _cmdId,
	style, WC_LISTBOX, _title, NULL, 0, NULL);

  }
//=======================>>> vListCmd::~vListCmd <<<=======================
  vListCmd::~vListCmd()
  {
    SysDebug(Constructor,"vListCmd::~vListCmd() Destructor\n")
  }
//==================>>> vListCmd::GetCmdValue <<<=========================
  int vListCmd::GetCmdValue(ItemVal id) VCONST
  {
    if (id != _cmdId)
	return -1;
    return _curSelection;       // return currently selected item
  }
//=====================>>> vListCmd::SetCmdVal <<<=========================
  void vListCmd::SetCmdVal(ItemVal val, ItemSetType st)
  {
    SysDebug2(Misc,"vListCmd::SetCmdVal(val:%d, type:%d)\n",val,st)
    HWND myHwnd = GetMyHwnd(_cmdId);

    switch (st)
    {
      case Sensitive:
	_Sensitive = val;               // set
	WinEnableWindow (myHwnd, val);
	break;

      case Hidden:
	if (val)
        {
	  WinShowWindow (myHwnd, FALSE);
          _isVisible = 0;
        }
	else
        {
	  WinShowWindow (myHwnd, TRUE);
          _isVisible = 1;
        }
	break;

      case ChangeList:
      case ChangeListPtr:
      {
	if (st == ChangeListPtr)
	    _itemList = dlgCmd->itemList;
	  // Change list is used both for initial display,
	  // and when user changes the list.
	  WinSendDlgItemMsg(_parentWin->getParent(),
		_cmdId, LM_DELETEALL,0,0); // Clear current

	  int oldMax = _maxWidth;         // track current max width
	  SetupList();                    // resetup the list
	  if (oldMax > _maxWidth)
	    _maxWidth = oldMax;         // don't let it get narrower

	  // populate the listbox, disable updates to speed it up
	  WinEnableWindowUpdate(myHwnd, FALSE);
	  for (int ixx = 0 ; ixx < _numItems ; ++ixx)
	  {
	    // Add each item to the list
//	    WinSendMsg(myHwnd, LM_INSERTITEM, MPFROMLONG(ixx), MPFROMP(_fullList[ixx]));
	    WinInsertLboxItem(myHwnd, ixx, _fullList[ixx]);
	  }
	  WinEnableWindow (myHwnd, _Sensitive);

	  if (_isVisible)
	    WinShowWindow(myHwnd,TRUE);
	  else
            WinShowWindow(myHwnd,FALSE);

	  _curSelection = val;
	  WinSendDlgItemMsg(_parentWin->getParent(),
		_cmdId, LM_SELECTITEM, MPFROMLONG(_curSelection), (MPARAM) TRUE);
	  return;
      }

      case Value:       // select a given item
      {
	if (val >= _numItems )
	    return;
	_curSelection = val;    // change the current value
	if (val < 0)            // unselect
	  {
	    _curSelection = -1;
	    return;
	  }
	// Now set appropriate _curSelection
	// in windows, -1 means unselect, so this works for both
	WinSendDlgItemMsg(_parentWin->getParent(),
	    _cmdId, LM_SELECTITEM, MPFROMLONG(_curSelection), (MPARAM) TRUE);
	break;
      }
    }
  }

//====================>>> vListCmd::SetupList <<<=======================
  void vListCmd::SetupList(void)
  {
    // Set up the list for use
    int len;
    _curSelection = -1;
    _fullList = (char**)_itemList;      // private copy of list
    // Calculate widest item and number of items
    for ( _numItems = 0 ; _fullList && _fullList[_numItems] != 0 ; ++_numItems)
      {
	len = strlen(_fullList[_numItems]);     // strlen
	if (len > _maxWidth)
	    _maxWidth = len;            // track largest so far
      }
    if (_curSelection < 0)              // make a safe default choice
	_curSelection = 0;
    else if (_curSelection >= _numItems)
	_curSelection = _numItems - 1;
    // Note that at this point _numItems is how many items are
    // in the user supplied list.
  }
//===================>>> vListCmd::CmdCallback <<<=======================
  void vListCmd::CmdCallback(UINT uMsg, MPARAM mp1, MPARAM mp2)
  {
    // See if we are getting a message we care about
//	SysDebug1(OS2Dev,"vListCmd::CmdCallBack \n")
    if (uMsg == WM_CONTROL)
    {
      if (SHORT2FROMMP(mp1) == LN_SELECT || SHORT2FROMMP(mp1) == LN_ENTER)
      {
	// Retrieve the current selection
	if ((_curSelection = (LONG) WinSendDlgItemMsg(_parentWin->getParent(),
		_cmdId, LM_QUERYSELECTION, 0, 0)) ==  LIT_NONE)
	{
	  _curSelection = -1;
	  return;
	}

	if (_curSelection >= _numItems )    // Safety check
	  _curSelection = -1;

	if (!(dlgCmd->attrs & CA_NoNotify)) // Notify on each selection?
	  _parentWin->ProcessCmd(_cmdId, _curSelection, dlgCmd->cmdType);
      }
    }
  }
