private void OnDown()
 {
   OnSelectionChanged();
   Action action = new Action();
   action.wID = Action.ActionType.ACTION_MOVE_DOWN;
   if (_listType == GUIListControl.ListType.CONTROL_LIST)
   {
     _listType = GUIListControl.ListType.CONTROL_UPDOWN;
     if (_upDownControl != null)
     {
       if (_spinCanFocus)
       {
         _upDownControl.Focus = true;
       }
       else
       {
         _listType = GUIListControl.ListType.CONTROL_LIST;
         this.Focus = true;
         base.OnAction(action);
       }
     }
   }
   else if (_upDownControl != null)
   {
     _upDownControl.OnAction(action);
     if (!_upDownControl.Focus)
     {
       base.OnAction(action);
     }
   }
 }
    public override bool HitTest(int x, int y, out int controlID, out bool focused)
    {
      controlID = GetID;
      focused = Focus;
      int id;
      bool focus;
      if (_horizontalScrollbar != null)
      {
        if (_horizontalScrollbar.HitTest(x, y, out id, out focus))
        {
          return true;
        }
      }
      if (!base.HitTest(x, y, out id, out focus))
      {
        Focus = false;
        if (_upDownControl != null)
        {
          if (!_upDownControl.HitTest(x, y, out id, out focus))
          {
            return false;
          }
        }
      }

      if (_upDownControl != null)
      {
        if (_upDownControl.HitTest(x, y, out id, out focus))
        {
          if (_upDownControl.GetMaximum() > 1)
          {
            _listType = GUIListControl.ListType.CONTROL_UPDOWN;
            _upDownControl.Focus = true;
            if (!_upDownControl.Focus)
            {
              _listType = GUIListControl.ListType.CONTROL_LIST;
            }
            return true;
          }
          return true;
        }
      }

      _listType = GUIListControl.ListType.CONTROL_LIST;
      y -= _positionY;
      x -= _positionX;
      _cursorX = (x / _itemWidth);

      while (_cursorX > 0 && _offset + _cursorX >= _listItems.Count)
      {
        _cursorX--;
      }
      OnSelectionChanged();

      return true;
    }
    private void OnLeft()
    {
      Action action = new Action();
      action.wID = Action.ActionType.ACTION_MOVE_LEFT;
      if (_listType == GUIListControl.ListType.CONTROL_LIST)
      {
        //If scrolloffset larger than half the nr of items make scrolloffset that nr
        int maxScrollOffset = _columns / 2;
        if (_scrollStartOffset > maxScrollOffset)
        {
          _scrollStartOffset = maxScrollOffset;
        }

        if (_scrollingLeft)
        {
          _scrollCounter = 0;
          _scrollingLeft = false;
          _offset--;
          int iPage = _offset / (_columns);
          if ((_offset % (_columns)) != 0)
          {
            iPage++;
          }
          if (_upDownControl != null && _spinCanFocus)
          {
            _upDownControl.Focus = true;
          }
          else
          {
            _listType = GUIListControl.ListType.CONTROL_LIST;
            this.Focus = true;
            base.OnAction(action);
          }
        }

        if (_cursorX > 0 && (_cursorX > _scrollStartOffset || _offset == 0))
        {
          _cursorX--;
        }
        else if (_cursorX <= _scrollStartOffset && _offset != 0)
        {
          _scrollCounter = _itemWidth;
          _scrollingLeft = true;
        }
        else
        {
          base.OnAction(action);
        }
        OnSelectionChanged();
      }
      else if (_upDownControl != null)
      {
        if (_upDownControl.SelectedButton == GUISpinControl.SpinSelect.SPIN_BUTTON_DOWN)
        {
          _upDownControl.Focus = false;
          _listType = GUIListControl.ListType.CONTROL_LIST;
          this.Focus = true;
        }
        else
        {
          _upDownControl.OnAction(action);
        }
        if (!_upDownControl.Focus)
        {
          _listType = GUIListControl.ListType.CONTROL_LIST;
        }
        OnSelectionChanged();
      }
    }
 private bool OnUp()
 {
   OnSelectionChanged();
   Action action = new Action();
   action.wID = Action.ActionType.ACTION_MOVE_UP;
   if (_listType == GUIListControl.ListType.CONTROL_LIST)
   {
     return false;
   }
   else if (_upDownControl != null)
   {
     if (_upDownControl.SelectedButton == GUISpinControl.SpinSelect.SPIN_BUTTON_DOWN ||
         _upDownControl.SelectedButton == GUISpinControl.SpinSelect.SPIN_BUTTON_UP)
     {
       _upDownControl.Focus = false;
       _listType = GUIListControl.ListType.CONTROL_LIST;
       this.Focus = true;
     }
     else
     {
       _upDownControl.OnAction(action);
     }
     if (!_upDownControl.Focus)
     {
       _listType = GUIListControl.ListType.CONTROL_LIST;
     }
   }
   return true;
 }
    public override bool OnMessage(GUIMessage message)
    {
      if (message.TargetControlId == GetID)
      {
        if (message.SenderControlId == 0)
        {
          if (message.Message == GUIMessage.MessageType.GUI_MSG_CLICKED)
          {
            _offset = (_upDownControl.Value - 1) * (_columns);
            _refresh = true;
            OnSelectionChanged();
          }
        }
        if (message.Message == GUIMessage.MessageType.GUI_MSG_GET_SELECTED_ITEM)
        {
          int iItem = _offset + _cursorX;
          if (iItem >= 0 && iItem < _listItems.Count)
          {
            message.Object = _listItems[iItem];
          }
          else
          {
            message.Object = null;
          }
          _refresh = true;
          return true;
        }

        if (message.Message == GUIMessage.MessageType.GUI_MSG_REFRESH)
        {
          GUITextureManager.CleanupThumbs();
          foreach (GUIListItem item in _listItems)
          {
            item.FreeMemory();
          }
          _refresh = true;
          if (_imageInfo != null)
          {
            _imageInfo.SafeDispose();
            _imageInfo.AllocResources();
            _imageInfo.DoUpdate();
          }
          return true;
        }

        if (message.Message == GUIMessage.MessageType.GUI_MSG_GET_ITEM)
        {
          int iItem = message.Param1;
          if (iItem >= 0 && iItem < _listItems.Count)
          {
            message.Object = _listItems[iItem];
          }
          else
          {
            message.Object = null;
          }
          return true;
        }
        if (message.Message == GUIMessage.MessageType.GUI_MSG_LOSTFOCUS ||
            message.Message == GUIMessage.MessageType.GUI_MSG_SETFOCUS)
        {
          if (Disabled || !IsVisible || !CanFocus())
          {
            base.OnMessage(message);
            return true;
          }
          _listType = GUIListControl.ListType.CONTROL_LIST;
          _refresh = true;
        }

        if (message.Message == GUIMessage.MessageType.GUI_MSG_LABEL_ADD)
        {
          GUIListItem newItem = message.Object as GUIListItem;
          if (newItem != null)
          {
            _listItems.Add(newItem);
            int iItemsPerPage = _columns;
            int iPages = iItemsPerPage == 0 ? 0 : _listItems.Count / iItemsPerPage;
            if (iItemsPerPage != 0)
            {
              if ((_listItems.Count % iItemsPerPage) != 0)
              {
                iPages++;
              }
            }
            if (_upDownControl != null)
            {
              _upDownControl.SetRange(1, iPages);
              _upDownControl.Value = 1;
            }
            _refresh = true;
          }
        }

        if (message.Message == GUIMessage.MessageType.GUI_MSG_LABEL_RESET)
        {
          Clear();
        }

        if (message.Message == GUIMessage.MessageType.GUI_MSG_ITEMS)
        {
          message.Param1 = _listItems.Count;
        }

        if (message.Message == GUIMessage.MessageType.GUI_MSG_ITEM_SELECTED)
        {
          message.Param1 = _offset + _cursorX;
        }
        if (message.Message == GUIMessage.MessageType.GUI_MSG_ITEM_SELECT)
        {
          int iItem = message.Param1;
          SelectItemIndex(iItem);
        }
      }

      if (message.Message == GUIMessage.MessageType.GUI_MSG_ITEM_FOCUS)
      {
        foreach (GUIListItem item in _listItems)
        {
          item.Selected = false;
        }
        foreach (GUIListItem item in _listItems)
        {
          if (item.Path.Equals(message.Label, StringComparison.OrdinalIgnoreCase))
          {
            item.Selected = true;
            break;
          }
        }
      }

      if (message.Message == GUIMessage.MessageType.GUI_MSG_FILE_DOWNLOADING)
      {
        foreach (GUIListItem item in _listItems)
        {
          if (item.IsRemote)
          {
            if (message.Label == item.Path)
            {
              item.IsDownloading = true;
            }
          }
        }
      }

      if (message.Message == GUIMessage.MessageType.GUI_MSG_FILE_DOWNLOADED)
      {
        foreach (GUIListItem item in _listItems)
        {
          if (item.IsRemote)
          {
            if (message.Label == item.Path)
            {
              item.Path = message.Label2;
              item.IsRemote = false;
              item.IsDownloading = false;
            }
          }
        }
      }

      if (base.OnMessage(message))
      {
        return true;
      }

      return false;
    }
    private void OnRight()
    {
      Action action = new Action();
      action.wID = Action.ActionType.ACTION_MOVE_RIGHT;
      if (_listType == GUIListControl.ListType.CONTROL_LIST)
      {
        //If scrolloffset larger than half the nr of items make scrolloffset that nr
        int maxScrollOffset = _columns / 2;
        if (_scrollStartOffset > maxScrollOffset)
        {
          _scrollStartOffset = maxScrollOffset;
        }

        if (_scrollingRight)
        {
          _scrollingRight = false;
          _offset++;
          int iPage = _offset / (_columns);
          if ((_offset % (_columns)) != 0)
          {
            iPage++;
          }
          if (_upDownControl != null)
          {
            _upDownControl.Value = iPage + 1;
          }
        }

        // If cursor offset from edge or if left space smaller than scrollStartOffset
        if (_cursorX + 1 >= _columns - _scrollStartOffset &&
            _listItems.Count - (_offset + _cursorX + 1) > _scrollStartOffset)
        {
          _offset++;
          if (!ValidItem(_cursorX))
          {
            _offset--;
          }
          else
          {
            _offset--;
            _scrollCounter = _itemWidth;
            _scrollingRight = true;
          }
          OnSelectionChanged();
          return;
        }
        else
        {
          if (ValidItem(_cursorX + 1))
          {
            _cursorX++;
            OnSelectionChanged();
          }
          else
          {
            _listType = GUIListControl.ListType.CONTROL_LIST;
            this.Focus = true;
            base.OnAction(action);
          }
        }
      }
      else if (_upDownControl != null)
      {
        if (_upDownControl.SelectedButton == GUISpinControl.SpinSelect.SPIN_BUTTON_UP)
        {
          _upDownControl.Focus = false;
          _listType = GUIListControl.ListType.CONTROL_LIST;
          this.Focus = true;
        }
        else
        {
          _upDownControl.OnAction(action);
          if (!_upDownControl.Focus)
          {
            base.OnAction(action);
          }
        }
        OnSelectionChanged();
      }
    }
    public override bool HitTest(int x, int y, out int controlID, out bool focused)
    {
      controlID = GetID;
      focused = Focus;
      int id;
      bool focus;
      if (_verticalScrollBar.HitTest(x, y, out id, out focus))
      {
        return true;
      }
      if (!base.HitTest(x, y, out id, out focus))
      {
        Focus = false;
        return false;
      }
      if (_controlUpDown.HitTest(x, y, out id, out focus))
      {
        if (_controlUpDown.GetMaximum() > 1)
        {
          m_iSelect = GUIListControl.ListType.CONTROL_UPDOWN;
          _controlUpDown.Focus = true;
          if (!_controlUpDown.Focus)
          {
            m_iSelect = GUIListControl.ListType.CONTROL_LIST;
          }
          return true;
        }
        return true;
      }
      m_iSelect = GUIListControl.ListType.CONTROL_LIST;
      y -= _positionY;
      x -= _positionX;
      int iCursorY = (y / _itemHeight);
      int iCursorX = (x / _itemWidth);

      // Check item inside panel
      if (iCursorX < 0 || iCursorX >= _columnCount)
      {
        return false;
      }
      if (iCursorY < 0 || iCursorY >= _rowCount)
      {
        return false;
      }
      _cursorY = iCursorY;
      _cursorX = iCursorX;

      while (_cursorX > 0 && _offset + _cursorY * _columnCount + _cursorX >= _listItems.Count)
      {
        _cursorX--;
      }
      while (_cursorY > 0 && _offset + _cursorY * _columnCount + _cursorX >= _listItems.Count)
      {
        _cursorY--;
      }
      OnSelectionChanged();

      return true;
    }
    private void OnDown()
    {
      Action action = new Action();
      action.wID = Action.ActionType.ACTION_MOVE_DOWN;
      if (m_iSelect == GUIListControl.ListType.CONTROL_LIST)
      {
        if (_scrollingDown)
        {
          _scrollingDown = false;
          _offset += _columnCount;
          int iPage = _offset / (_rowCount * _columnCount);
          if ((_offset % (_rowCount * _columnCount)) != 0)
          {
            iPage++;
          }
          _controlUpDown.Value = iPage + 1;
          if (_scrollingDownLast)
          {
            _scrollingDownLast = false;
            _cursorX = _listItems.Count % _columnCount - 1 >= 0 ? _listItems.Count % _columnCount - 1 : 0;
          }
          if (_compensatingDown)
          {
            _cursorY -= 1;
            _compensatingDown = false;
            OnDown();
          }
        }
        int iMaxRows = _listItems.Count / _columnCount;
        int iHalfLastRowElements = _listItems.Count % _columnCount;
        if (iHalfLastRowElements > 0)
        {
          iMaxRows++;
        }
        int iCurrRow = (_offset + _columnCount + (_cursorY) * _columnCount) / _columnCount;
        //if (_cursorY + 1 > _rowCount - _scrollStartOffset && iCurrRow != iMaxRows) _cursorY--;
        int iNextRow = (_offset + _columnCount + (_cursorY + 1) * _columnCount) / _columnCount;

        //if ((_cursorY + 1 >= _rowCount - _scrollStartOffset) && (iNextRow <= iMaxRows - _scrollStartOffset))
        if ((_cursorY + 1 >= _rowCount - _scrollStartOffset) && (_offset + (_columnCount * _rowCount) < _listItems.Count))
          
        {
          // we reached the scroll row
          {
            _offset += _columnCount;
            if (!ValidItem(_cursorX, _cursorY))
            {
              // we reached the last row 
              _offset -= _columnCount;
              int iOffsetInc = _columnCount - _cursorX - 1 + iHalfLastRowElements;
              _offset += iOffsetInc;
              if (!ValidItem(_cursorX, _cursorY))
              {
                SetDownFocus(action, iOffsetInc);
              }
              else
              {
                _offset -= iOffsetInc;// +iHalfLastRowElements;
                _scrollCounter = _itemHeight;
                _scrollingDown = true;
                _scrollingDownLast = true;
              }
            }
            else
            {
              {
                _offset -= _columnCount;
                if (_cursorY > _rowCount - _scrollStartOffset - 1)
                  _compensatingDown = true;
                  //_cursorY -= 1;
                _scrollCounter = _itemHeight;
                _scrollingDown = true;
              }
            }

            OnSelectionChanged();
            _lastCommandTime = AnimationTimer.TickCount;
            return;
          }
        }
        else
        {
          if (ValidItem(_cursorX, _cursorY + 1))
          {
            _cursorY++;
          }
          else if (ValidItem(iHalfLastRowElements - 1, _cursorY + 1))
          {
            _cursorX = iHalfLastRowElements - 1;
            _cursorY++;
          }
          else
          {
            SetDownFocus(action, 0);
          }
          OnSelectionChanged();
        }
      }
      else
      {
        _controlUpDown.OnAction(action);
        if (!_controlUpDown.Focus)
        {
          m_iSelect = GUIListControl.ListType.CONTROL_LIST;
        }
      }
      _lastCommandTime = AnimationTimer.TickCount;
    }
    private void OnUp()
    {
      Action action = new Action();
      action.wID = Action.ActionType.ACTION_MOVE_UP;
      if (m_iSelect == GUIListControl.ListType.CONTROL_LIST)
      {
        if (_scrollingUp)
        {
          _scrollCounter = 0;
          _scrollingUp = false;
          _offset -= _columnCount;
          int iPage = _offset / (_rowCount * _columnCount);
          if ((_offset % (_rowCount * _columnCount)) != 0)
          {
            iPage++;
          }
          _controlUpDown.Value = iPage + 1;
          if (_compensatingUp)
          {
            _cursorY += 1;
            _compensatingUp = false;
            OnUp();
          }
        }

        if ((_cursorY > _scrollStartOffset) || ((_cursorY > 0) && (_offset == 0)))
        {
          _cursorY--;
        }
        else if (_cursorY <= _scrollStartOffset && _offset != 0)
        {
          if (_cursorY < _scrollStartOffset)
            _compensatingUp = true;
          _scrollCounter = _itemHeight;
          _scrollingUp = true;
        }
        else
        {
          if ((AnimationTimer.TickCount - _lastCommandTime) > _loopDelay)
          {
            //check if _downControlId is set -> then go to the window
            if (NavigateUp > 0)
            {
              GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_SETFOCUS, WindowId, GetID, NavigateUp,
                                              (int)action.wID, 0, null);
              GUIGraphicsContext.SendMessage(msg);
            }
            else
            {
              _offset = (CalculateRows(_listItems.Count) - _rowCount) * _columnCount;
              if (_offset < 0)
              {
                _offset = 0;
              }
              _cursorY = _rowCount - 1;
              //while (_offset + _cursorY * _columnCount + _cursorX >= _listItems.Count)
              //{
              //  _cursorY--;
              //}
              while (!ValidItem(_cursorX, _cursorY) && _cursorX > 0)
              {
                _cursorX--;
              }
            }
          }
        }
        OnSelectionChanged();
      }
      else
      {
        _controlUpDown.OnAction(action);
        if (_controlUpDown.SelectedButton == GUISpinControl.SpinSelect.SPIN_BUTTON_DOWN ||
            _controlUpDown.SelectedButton == GUISpinControl.SpinSelect.SPIN_BUTTON_UP)
        {
          _controlUpDown.Focus = false;
          m_iSelect = GUIListControl.ListType.CONTROL_LIST;
          Focus = true;
        }
        else
        {
          _controlUpDown.OnAction(action);
        }

        if (!_controlUpDown.Focus)
        {
          m_iSelect = GUIListControl.ListType.CONTROL_LIST;
        }
      }
      _lastCommandTime = AnimationTimer.TickCount;
    }
 private void OnLeft()
 {
   Action action = new Action();
   action.wID = Action.ActionType.ACTION_MOVE_LEFT;
   if (m_iSelect == GUIListControl.ListType.CONTROL_LIST)
   {
     if (_cursorX > 0)
     {
       _cursorX--;
       OnSelectionChanged();
       return;
     }
     base.OnAction(action);
     OnSelectionChanged();
   }
   else
   {
     _controlUpDown.OnAction(action);
     if (!_controlUpDown.Focus)
     {
       m_iSelect = GUIListControl.ListType.CONTROL_LIST;
     }
     OnSelectionChanged();
   }
 }
    private void OnRight()
    {
      Action action = new Action();
      action.wID = Action.ActionType.ACTION_MOVE_RIGHT;
      if (m_iSelect == GUIListControl.ListType.CONTROL_LIST)
      {
        if (_cursorX + 1 < _columnCount && ValidItem(_cursorX + 1, _cursorY))
        {
          _cursorX++;
          OnSelectionChanged();
          return;
        }

        if (_controlUpDown.GetMaximum() > 1 && _spinCanFocus)
        {
          m_iSelect = GUIListControl.ListType.CONTROL_UPDOWN;
          _controlUpDown.Focus = true;
        }
        else
        {
          base.OnAction(action);
        }
        OnSelectionChanged();
      }
      else
      {
        _controlUpDown.OnAction(action);
        if (!_controlUpDown.Focus)
        {
          base.OnAction(action);
        }
        OnSelectionChanged();
      }
    }