context: // ImageListPopup by John O'Byrne
  // This class pops up window displaying the different images
  // contained in an ImageList and allows to select one.
  // History: 24/02/2003 : Initial Release
  //          25/02/2003 : Added Keyboard support (arrows + space or enter to validate)
  //                       Added Drag'n'Drop Support (disabled by default) - The selected Image
  //                       and its Id are available to the drop target
  
  using System;
  using System.ComponentModel;
  using System.Drawing;
  using System.Windows.Forms;
  
  namespace Creek.UI.MozOptions
  {
  
      #region Delegates
  
      public delegate void ImageListPanelEventHandler(object sender, ImageListPanelEventArgs ilpea);
  
      #endregion
  
      [ToolboxItem(false)]
      public class ImageListPanel : Control
      {
          #region Protected Member Variables
  
          protected Bitmap _Bitmap = null;
          protected bool _bIsMouseDown = false;
  
          protected int _defaultImage;
          protected ImageList _imageList = null;
          protected int _nBitmapHeight = 0;
          protected int _nBitmapWidth = 0;
          protected int _nColumns = 0;
          protected int _nCoordX = -1;
          protected int _nCoordY = -1;
          protected int _nHSpace = 0;
          protected int _nItemHeight = 0;
          protected int _nItemWidth = 0;
          protected int _nRows = 0;
          protected int _nVSpace = 0;
  
          #endregion
  
          #region Public Properties
  
          public Color BackgroundColor = Color.FromArgb(255, 255, 255);
          public Color BackgroundOverColor = Color.FromArgb(241, 238, 231);
          public Color BorderColor = Color.FromArgb(0, 16, 123);
          public bool EnableDragDrop = false;
          public Color HLinesColor = Color.FromArgb(222, 222, 222);
          public Color VLinesColor = Color.FromArgb(165, 182, 222);
  
          #endregion
  
          #region Events
  
          public event ImageListPanelEventHandler ItemClick = null;
  
          #endregion
  
          #region Constructor
  
          #endregion
  
          #region Public Methods
  
          public bool Init(ImageList imageList, int nHSpace, int nVSpace, int nColumns, int defaultImage)
          {
              int nRows;
  
              Brush bgBrush = new SolidBrush(BackgroundColor);
              var vPen = new Pen(VLinesColor);
              var hPen = new Pen(HLinesColor);
              var borderPen = new Pen(BorderColor);
  
              _imageList = imageList;
              _nColumns = nColumns;
  
              _defaultImage = defaultImage;
              if (_defaultImage > _imageList.Images.Count)
                  _defaultImage = _imageList.Images.Count;
              if (_defaultImage < 0) _defaultImage = -1;
  
  
              nRows = imageList.Images.Count/_nColumns;
              if (imageList.Images.Count%_nColumns > 0) nRows++;
  
              _nRows = nRows;
              _nHSpace = nHSpace;
              _nVSpace = nVSpace;
              _nItemWidth = _imageList.ImageSize.Width + nHSpace;
              _nItemHeight = _imageList.ImageSize.Height + nVSpace;
              _nBitmapWidth = _nColumns*_nItemWidth + 1;
              _nBitmapHeight = _nRows*_nItemHeight + 1;
              Width = _nBitmapWidth;
              Height = _nBitmapHeight;
  
  
              _Bitmap = new Bitmap(_nBitmapWidth, _nBitmapHeight);
              Graphics grfx = Graphics.FromImage(_Bitmap);
              grfx.FillRectangle(bgBrush, 0, 0, _nBitmapWidth, _nBitmapHeight);
              for (int i = 0; i < _nColumns; i++)
                  grfx.DrawLine(vPen, i*_nItemWidth, 0, i*_nItemWidth, _nBitmapHeight - 1);
              for (int i = 0; i < _nRows; i++)
                  grfx.DrawLine(hPen, 0, i*_nItemHeight, _nBitmapWidth - 1, i*_nItemHeight);
  
              grfx.DrawRectangle(borderPen, 0, 0, _nBitmapWidth - 1, _nBitmapHeight - 1);
  
              for (int i = 0; i < _nColumns; i++)
                  for (int j = 0; j < _nRows; j++)
                  {
                      if ((j*_nColumns + i) < imageList.Images.Count)
                          imageList.Draw(grfx,
                                         i*_nItemWidth + _nHSpace/2,
                                         j*_nItemHeight + nVSpace/2,
                                         imageList.ImageSize.Width,
                                         imageList.ImageSize.Height,
                                         j*_nColumns + i);
                  }
  
              /*	int a = (_defaultImage / _nColumns);  // rad
  			int b = (_defaultImage % _nColumns); // kolumn;
  
  			_nCoordX = b*(_nItemWidth+_nHSpace/2)-1;
  			_nCoordY = a*(_nItemHeight+nVSpace/2)-1;
  		*/
  
              // Clean up
              bgBrush.Dispose();
              vPen.Dispose();
              hPen.Dispose();
              borderPen.Dispose();
  
              Invalidate();
              return true;
          }
  
          public void Show(int x, int y)
          {
              Left = x;
              Top = y;
              base.Show();
          }
  
          #endregion
  
          #region Overrides
  
          protected override void OnMouseLeave(EventArgs ea)
          {
              // We repaint the popup if the mouse is no more over it
              base.OnMouseLeave(ea);
              _nCoordX = -1;
              _nCoordY = -1;
              Invalidate();
          }
  
          /*protected override void OnDeactivate(EventArgs ea)
  		{
  			// If the form loses focus, we hide it
  			this.Hide();
  		}*/
  
          protected override void OnKeyDown(KeyEventArgs kea)
          {
              if (_nCoordX == -1 || _nCoordY == -1)
              {
                  _nCoordX = 0;
                  _nCoordY = 0;
                  Invalidate();
              }
              else
              {
                  switch (kea.KeyCode)
                  {
                      case Keys.Down:
                          if (_nCoordY < _nRows - 1)
                          {
                              _nCoordY++;
                              Invalidate();
                          }
                          break;
                      case Keys.Up:
                          if (_nCoordY > 0)
                          {
                              _nCoordY--;
                              Invalidate();
                          }
                          break;
                      case Keys.Right:
                          if (_nCoordX < _nColumns - 1)
                          {
                              _nCoordX++;
                              Invalidate();
                          }
                          break;
                      case Keys.Left:
                          if (_nCoordX > 0)
                          {
                              _nCoordX--;
                              Invalidate();
                          }
                          break;
                      case Keys.Enter:
                      case Keys.Space:
                          // We fire the event only when the mouse is released
                          int nImageId = _nCoordY*_nColumns + _nCoordX;
                          if (ItemClick != null && nImageId >= 0 && nImageId < _imageList.Images.Count)
                          {
  
gt:                             ItemClick(this, new ImageListPanelEventArgs(nImageId));