using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 갤러리 컨트롤
/// </summary>
public partial class GalleryControl : UserControl
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 뷰포트 너비
/// </summary>
private int viewportWidth;
/// <summary>
/// 뷰포트 높이
/// </summary>
private int viewportHeight;
/// <summary>
/// 항목 너비
/// </summary>
private int itemWidth = 200;
/// <summary>
/// 항목 높이
/// </summary>
private int itemHeight = 200;
/// <summary>
/// 항목 리스트
/// </summary>
private List<GalleryItem> itemList = null;
/// <summary>
/// 항목 수
/// </summary>
private int itemCount;
/// <summary>
/// 뷰포트 항목 X 수
/// </summary>
private int viewportItemXCount;
/// <summary>
/// 뷰포트 항목 Y 수
/// </summary>
private int viewportItemYCount;
/// <summary>
/// 뷰포트 항목 수
/// </summary>
private int viewportItemCount;
/// <summary>
/// 스크롤바 너비
/// </summary>
private int scrollBarWidth = 18;
/// <summary>
/// 컨텐트 너비
/// </summary>
private int contentWidth;
/// <summary>
/// 컨텐트 높이
/// </summary>
private int contentHeight;
/// <summary>
/// 스크롤 Y
/// </summary>
private int scrollY = 0;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 뷰포트 너비 - ViewportWidth
/// <summary>
/// 뷰포트 너비
/// </summary>
public int ViewportWidth
{
get
{
return this.viewportWidth;
}
}
#endregion
#region 뷰포트 높이 - ViewportHeight
/// <summary>
/// 뷰포트 높이
/// </summary>
public int ViewportHeight
{
get
{
return this.viewportHeight;
}
}
#endregion
#region 항목 너비 - ItemWidth
/// <summary>
/// 항목 너비
/// </summary>
public int ItemWidth
{
get
{
return this.itemWidth;
}
set
{
if(this.itemWidth == value)
{
return;
}
this.itemWidth = value;
Calculate();
}
}
#endregion
#region 항목 높이 - ItemHeight
/// <summary>
/// 항목 높이
/// </summary>
public int ItemHeight
{
get
{
return this.itemHeight;
}
set
{
if(this.itemHeight == value)
{
return;
}
this.itemHeight = value;
Calculate();
}
}
#endregion
#region 항목 리스트 - ItemList
/// <summary>
/// 항목 리스트
/// </summary>
public List<GalleryItem> ItemList
{
get
{
return this.itemList;
}
set
{
if(this.itemList == value)
{
return;
}
this.itemList = value;
Calculate();
}
}
#endregion
#region 항목 수 - ItemCount
/// <summary>
/// 항목 수
/// </summary>
public int ItemCount
{
get
{
return this.itemCount;
}
}
#endregion
#region 뷰포트 항목 X 수 - ViewportItemXCount
/// <summary>
/// 뷰포트 항목 X 수
/// </summary>
public int ViewportItemXCount
{
get
{
return this.viewportItemXCount;
}
}
#endregion
#region 뷰포트 항목 Y 수 - ViewportItemYCount
/// <summary>
/// 뷰포트 항목 Y 수
/// </summary>
public int ViewportItemYCount
{
get
{
return this.viewportItemYCount;
}
}
#endregion
#region 뷰포트 항목 수 - ViewportItemCount
/// <summary>
/// 뷰포트 항목 수
/// </summary>
public int ViewportItemCount
{
get
{
return this.viewportItemCount;
}
}
#endregion
#region 스크롤바 너비 - ScrollBarWidth
/// <summary>
/// 스크롤바 너비
/// </summary>
public int ScrollBarWidth
{
get
{
return this.scrollBarWidth;
}
set
{
if(this.scrollBarWidth == value)
{
return;
}
this.scrollBarWidth = value;
this.vScrollBar.Width = this.scrollBarWidth - 1;
Calculate();
}
}
#endregion
#region 컨텐트 너비 - ContentWidth
/// <summary>
/// 컨텐트 너비
/// </summary>
public int ContentWidth
{
get
{
return this.contentWidth;
}
}
#endregion
#region 컨텐트 높이 - ContentHeight
/// <summary>
/// 컨텐트 높이
/// </summary>
public int ContentHeight
{
get
{
return this.contentHeight;
}
}
#endregion
#region 스크롤 Y - ScrollY
/// <summary>
/// 스크롤 Y
/// </summary>
public int ScrollY
{
get
{
return this.scrollY;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - GalleryControl()
/// <summary>
/// 생성자
/// </summary>
public GalleryControl()
{
InitializeComponent();
SetStyle(ControlStyles.DoubleBuffer , true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint , true);
this.vScrollBar.Width = this.scrollBarWidth - 1;
this.vScrollBar.Visible = false;
SizeChanged += UserControl_SizeChanged;
Paint += UserControl_Paint;
MouseWheel += UserControl_MouseWheel;
this.vScrollBar.ValueChanged += vScrollBar_ValueChanged;
this.vScrollBar.MouseWheel += vScrollBar_MouseWheel;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 사용자 컨트롤 크기 변경시 처리하기 - UserControl_SizeChanged(sender, e)
/// <summary>
/// 사용자 컨트롤 크기 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_SizeChanged(object sender, EventArgs e)
{
Calculate();
}
#endregion
#region 사용자 컨트롤 페인트시 처리하기 - UserControl_Paint(sender, e)
/// <summary>
/// 사용자 컨트롤 페인트시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = e.Graphics;
graphics.Clear(Color.White);
if(this.itemCount > 0 && this.viewportItemCount > 0)
{
int viewportStartY = this.scrollY;
int viewportEndY = this.scrollY + this.viewportHeight;
int itemStartRowIndex = viewportStartY / this.itemHeight;
int itemEndRowIndex = viewportEndY / this.itemHeight;
for(int y = itemStartRowIndex; y <= itemEndRowIndex; y++)
{
for(int x = 0; x < this.viewportItemXCount; x++)
{
int sequenceIndex = GalleryHelper.GetSequenceIndex(this.viewportItemXCount, y, x);
if(sequenceIndex > this.itemList.Count - 1)
{
continue;
}
GalleryItem item = this.itemList[sequenceIndex];
int itemX = x * this.itemWidth;
int itemY = y * this.itemHeight - this.scrollY;
GalleryHelper.DrawItem(graphics, itemX, itemY, this.itemWidth, this.itemHeight, item);
}
}
}
}
#endregion
#region 사용자 컨트롤 마우스 휠 처리하기 - UserControl_MouseWheel(sender, e)
/// <summary>
/// 사용자 컨트롤 마우스 휠 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_MouseWheel(object sender, MouseEventArgs e)
{
if(this.vScrollBar.Visible)
{
this.vScrollBar.Value = Math.Max(this.vScrollBar.Minimum, Math.Min(this.vScrollBar.Maximum, this.vScrollBar.Value - e.Delta));
}
}
#endregion
#region 수직 스크롤바 값 변경시 처리하기 - vScrollBar_ValueChanged(sender, e)
/// <summary>
/// 수직 스크롤바 값 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void vScrollBar_ValueChanged(object sender, EventArgs e)
{
this.scrollY = this.vScrollBar.Value;
Invalidate();
}
#endregion
#region 수직 스크롤바 마우스 휠 처리하기 - vScrollBar_MouseWheel(sender, e)
/// <summary>
/// 수직 스크롤바 마우스 휠 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void vScrollBar_MouseWheel(object sender, MouseEventArgs e)
{
this.vScrollBar.Value = Math.Max(this.vScrollBar.Minimum, Math.Min(this.vScrollBar.Maximum, this.vScrollBar.Value - e.Delta));
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 스크롤바 설정하기 - SetScrollBar()
/// <summary>
/// 스크롤바 설정하기
/// </summary>
private void SetScrollBar()
{
this.vScrollBar.ValueChanged -= vScrollBar_ValueChanged;
this.vScrollBar.MouseWheel -= vScrollBar_MouseWheel;
if(this.viewportItemCount == 0)
{
this.vScrollBar.Visible = false;
this.scrollY = 0;
}
else
{
if(this.itemCount == 0)
{
this.vScrollBar.Visible = false;
this.scrollY = 0;
}
else
{
if(this.itemCount > this.viewportItemCount)
{
this.vScrollBar.Visible = true;
this.vScrollBar.Minimum = 0;
this.vScrollBar.Maximum = this.contentHeight - this.viewportHeight + 10;
this.scrollY = Math.Max(this.vScrollBar.Minimum, Math.Min(this.scrollY, this.vScrollBar.Maximum));
this.vScrollBar.Value = this.scrollY;
}
else
{
this.vScrollBar.Visible = false;
this.scrollY = 0;
}
}
}
this.vScrollBar.ValueChanged += vScrollBar_ValueChanged;
this.vScrollBar.MouseWheel += vScrollBar_MouseWheel;
}
#endregion
#region 계산하기 - Calculate()
/// <summary>
/// 계산하기
/// </summary>
private void Calculate()
{
int temporaryViewportWidth = ClientSize.Width;
int temporaryViewportHeight = ClientSize.Height;
int temporaryViewportItemXCount = temporaryViewportWidth / this.itemWidth;
int temporaryViewportItemYCount = temporaryViewportHeight / this.itemHeight;
int temporaryViewportItemCount = temporaryViewportItemXCount * temporaryViewportItemYCount;
if(temporaryViewportItemCount == 0)
{
this.viewportItemCount = 0;
}
else
{
this.itemCount = this.itemList == null ? 0 : this.itemList.Count;
if(this.itemCount == 0)
{
this.viewportItemCount = 0;
}
else
{
if(this.itemCount > temporaryViewportItemCount)
{
temporaryViewportWidth = ClientSize.Width - this.scrollBarWidth;
temporaryViewportHeight = ClientSize.Height;
temporaryViewportItemXCount = temporaryViewportWidth / this.itemWidth;
temporaryViewportItemYCount = temporaryViewportHeight / this.itemHeight;
temporaryViewportItemCount = temporaryViewportItemXCount * temporaryViewportItemYCount;
if(temporaryViewportItemCount == 0)
{
this.viewportItemCount = 0;
}
else
{
this.viewportWidth = temporaryViewportWidth;
this.viewportHeight = temporaryViewportHeight;
this.viewportItemXCount = temporaryViewportItemXCount;
this.viewportItemYCount = temporaryViewportItemYCount;
this.viewportItemCount = temporaryViewportItemCount;
this.contentWidth = this.viewportItemXCount * this.itemWidth;
this.contentHeight = (GalleryHelper.GetRowIndex(this.viewportItemXCount, this.itemCount - 1) + 1) * this.itemHeight;
}
}
else
{
this.viewportWidth = temporaryViewportWidth;
this.viewportHeight = temporaryViewportHeight;
this.viewportItemXCount = temporaryViewportItemXCount;
this.viewportItemYCount = temporaryViewportItemYCount;
this.viewportItemCount = temporaryViewportItemCount;
this.contentWidth = this.viewportItemXCount * this.itemWidth;
this.contentHeight = (GalleryHelper.GetRowIndex(this.viewportItemXCount, this.itemCount - 1) + 1) * this.itemHeight;
}
}
}
SetScrollBar();
Invalidate();
}
#endregion
}
}