|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class cLibPicTray
{
[Serializable]
public struct udtTrayLoc
{
public double angle;
public double x;
public double y;
}
[Serializable]
public struct udtPicBoxTrayElement
{
public classPicBox picBox;
public udtTrayLoc trayLoc;
public double dblXOverYRatio;
}
public struct udtCartesian
{
public double x;
public double y;
}
public enum enuTurning { Clockwise = -1, notTurning, CounterClockwise }
public udtPicBoxTrayElement[] udrPicBoxTrayElements;
public double dblCurrentAngle;
double dblMinSizeFraction = 0.5;
udtCartesian udrMaxSizeFraction = new udtCartesian();
udtCartesian udrCenterFraction = new udtCartesian();
double dblTurnAngleStep;
enuTurning turningAngle;
double dblCircleRadius;
double dblCircleRadiusFactor;
public System.Windows.Forms.PictureBox picBackground = new System.Windows.Forms.PictureBox();
udtCartesian udrMaxSize; // maximum picture size
udtCartesian udrCenter; // center of the circle
udtCartesian udrMouse;
public int intSelected;
public bool bolMouseMoveOverAutoSelect = false;
public System.Threading.Thread clickPicThread;
public bool bolClickPicBool;
public bool bolPopUpClickedPic = false;
public bool bolCarousel = false;
public System.Windows.Forms.Timer tmrRotate = new System.Windows.Forms.Timer();
public cLibPicTray()
{
picBackground.SizeChanged += new EventHandler(picBackground_SizeChanged);
tmrRotate.Tick += new EventHandler(tmrRotate_Tick);
resetStandardParameters();
udrPicBoxTrayElements = null;
turningAngle = enuTurning.notTurning;
handle_SizeChange();
}
public void resetStandardParameters()
{
dblTurnAngleStep = Math.PI / 64;
setCircleRadius(1.5);
setMaxHeightFraction(0.7);
setMaxWidthFraction(1);
setMinSizeFraction(0.2);
setCenterFraction_X(0.5);
setCenterFraction_Y(0.15);
bolMouseMoveOverAutoSelect = true;
bolClickPicBool = false;
bolPopUpClickedPic = false;
}
public void setCenterFraction_X(double dblFractionFromLeftOfPanel)
{ udrCenterFraction.x = dblFractionFromLeftOfPanel; }
public void setCenterFraction_Y(double dblFractionFromTopOfPanel)
{ udrCenterFraction.y = dblFractionFromTopOfPanel; }
public void setBackGroundImage(string strFilename)
{ picBackground.Load(strFilename); }
public void setBackGroundImage(System.Drawing.Image imgLocal)
{ picBackground.Image = imgLocal; }
public void setCircleRadius(double dblFactor)
{ dblCircleRadiusFactor = dblFactor; }
public void setMinSizeFraction(double dblMinSize)
{
if (dblMinSizeFraction < 0 || dblMinSizeFraction > 1)
return;
dblMinSizeFraction = dblMinSize;
}
public void setMaxWidthFraction(double dblFractionOfPanelWidth)
{ udrMaxSizeFraction.x = dblFractionOfPanelWidth; }
public void setMaxHeightFraction(double dblFractionOfPanelHeight)
{ udrMaxSizeFraction.y = dblFractionOfPanelHeight; }
int getSelectedImage(System.Windows.Forms.MouseEventArgs e)
{
udrMouse.x = e.X; udrMouse.y = e.Y;
// set current image selected by mouse position - front to back
int[] intRankingIndices = getRankingIndices();
if (intRankingIndices == null)
return -1;
int intLocalSelected = -1;
for (int intPicCounter = intRankingIndices.Length - 1; intPicCounter >= 0; intPicCounter--)
{
if (udrMouse.x > udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Left
&& udrMouse.x < udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Left + udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Width)
if (udrMouse.y > udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Top
&& udrMouse.y < udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Top + udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Height)
{
intLocalSelected = intRankingIndices[intPicCounter];
break;
}
}
return intLocalSelected;
}
void handle_PopUpPic(int intSelected)
{
try
{
cLibPicBoxViewer cLibPicBox = new cLibPicBoxViewer (udrPicBoxTrayElements[intSelected].picBox.Image, "");
cLibPicBox.resizeToFitImage();
}
catch (Exception) { }
}
void handle_newSelection()
{
if (intSelected >= udrPicBoxTrayElements.Length)
intSelected = udrPicBoxTrayElements.Length - 1;
if (intSelected >= 0)
{
if (udrPicBoxTrayElements[intSelected].trayLoc.x > 0)
turningAngle = enuTurning.Clockwise;
else
turningAngle = enuTurning.CounterClockwise;
tmrRotate.Enabled = true;
}
}
void tmrRotate_Tick(object sender, EventArgs e)
{
dblCurrentAngle += (int)turningAngle * dblTurnAngleStep;
if (dblCurrentAngle < 0)
dblCurrentAngle += (Math.PI * 2);
else if (dblCurrentAngle > 2 * Math.PI)
dblCurrentAngle -= (Math.PI * 2);
repositionTray();
}
public void setTurningPeriod(int intDelayInMilliseconds)
{
if (intDelayInMilliseconds > 0)
{
tmrRotate.Interval = intDelayInMilliseconds;
tmrRotate.Enabled = true;
}
else
tmrRotate.Enabled = false;
}
public void setTurningAngularStepSize(double dblAngularStepSize)
{
dblTurnAngleStep = Math.Sign(dblTurnAngleStep) * dblAngularStepSize;
tmrRotate.Enabled = (dblTurnAngleStep != 0);
}
public void setRotatingDirection(enuTurning turningDirection)
{
turningAngle = turningDirection;
tmrRotate.Enabled = (turningDirection != enuTurning.notTurning);
intSelected = -1;
}
void picBackground_SizeChanged(object sender, EventArgs e)
{ handle_SizeChange(); }
public void handle_SizeChange()
{
udrMaxSize.x = (picBackground.Width * udrMaxSizeFraction.x);
udrMaxSize.y = picBackground.Height * udrMaxSizeFraction.y;
udrCenter.x = picBackground.Width * udrCenterFraction.x;
udrCenter.y = picBackground.Height * udrCenterFraction.y;
double dblMaxWidthCircle = picBackground.Width * 0.5;
double dblMaxHeightCircle = picBackground.Height * 0.5;
if (dblMaxHeightCircle < dblMaxWidthCircle)
dblCircleRadius = dblMaxHeightCircle / 5;
else
dblCircleRadius = dblMaxWidthCircle / 5;
dblCircleRadius *= dblCircleRadiusFactor;
repositionTray();
}
public void deletePicture()
{ deletePicture(intSelected); }
public void deletePicture(int intIndexToDelete)
{
if (intIndexToDelete >= 0 && intIndexToDelete < udrPicBoxTrayElements.Length)
{
udrPicBoxTrayElements[intIndexToDelete].picBox.Dispose();
for (int intPicCounter = intIndexToDelete; intPicCounter < udrPicBoxTrayElements.Length - 1; intPicCounter++)
udrPicBoxTrayElements[intPicCounter] = udrPicBoxTrayElements[intPicCounter + 1];
Array.Resize<udtPicBoxTrayElement>(ref udrPicBoxTrayElements, udrPicBoxTrayElements.Length - 1);
}
repositionTray();
handle_newSelection();
}
public void addPicBox(ref System.Windows.Forms.PictureBox PicThisBox_new)
{
if (udrPicBoxTrayElements == null)
udrPicBoxTrayElements = new udtPicBoxTrayElement[1];
else
Array.Resize<udtPicBoxTrayElement>(ref udrPicBoxTrayElements, udrPicBoxTrayElements.Length + 1);
classPicBox PicThisBox = new classPicBox();
PicThisBox.Image = PicThisBox_new.Image;
udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox = PicThisBox;
udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox.index = udrPicBoxTrayElements.Length - 1;
picBackground.Controls.Add(udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox);
PicThisBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].dblXOverYRatio = (double)udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox.Width / (double)udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox.Height;
PicThisBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
handle_SizeChange();
intSelected = udrPicBoxTrayElements.Length - 1;
repositionTray();
handle_newSelection();
udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox.MouseMove += new System.Windows.Forms.MouseEventHandler(picBox_MouseMove);
udrPicBoxTrayElements[udrPicBoxTrayElements.Length - 1].picBox.MouseClick += new System.Windows.Forms.MouseEventHandler(picBox_MouseClick);
}
void picBox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
{
classPicBox pb = (classPicBox)sender;
intSelected = pb.index;
bolClickPicBool = true;
handle_newSelection();
if (clickPicThread != null)
clickPicThread.Start();
if (bolPopUpClickedPic)
handle_PopUpPic(intSelected);
}
void picBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
classPicBox pb = (classPicBox)sender;
if (bolMouseMoveOverAutoSelect)
{
int intTempSelected = pb.index;
if (intTempSelected >= 0 & intTempSelected != intSelected)
{
intSelected = intTempSelected;
handle_newSelection();
}
}
}
//void lblTransparentLabel_MouseClick(object sender, MouseEventArgs e)
//{
// intSelected = getSelectedImage(e);
// bolClickPicBool = true;
// handle_newSelection();
// if (clickPicThread != null)
// clickPicThread.Start();
// if (bolPopUpClickedPic)
// handle_PopUpPic(intSelected);
//}
//void lblTransparentLabel_MouseMove(object sender, MouseEventArgs e)
//{
// if (bolMouseMoveOverAutoSelect)
// {
// int intTempSelected = getSelectedImage(e);
// if (intTempSelected >= 0 & intTempSelected != intSelected )
// {
// intSelected = intTempSelected;
// handle_newSelection();
// }
// }
//}
private int[] getRankingIndices()
{
// returns array of indices of elements as they appear back to front
//(nearest top of first first in order until reach the one nearest the bottom of the form as measured around unit circle)
int[] intRetVal;
//= new int[udrPicBoxTrayElements.Length];
try
{ intRetVal = new int[udrPicBoxTrayElements.Length]; }
catch (Exception) { return null; }
// rank them front to back
for (int intPicBoxCounter = 0; intPicBoxCounter < udrPicBoxTrayElements.Length; intPicBoxCounter++)
intRetVal[intPicBoxCounter] = intPicBoxCounter;
int intBestIndex, intTemp, intInnerLoop, intOuterLoop;
double dblBestValue;
for (intOuterLoop = 0; intOuterLoop < intRetVal.Length - 1; intOuterLoop++)
{
intBestIndex = intOuterLoop;
dblBestValue = udrPicBoxTrayElements[intRetVal[intOuterLoop]].trayLoc.y;
for (intInnerLoop = intOuterLoop + 1; intInnerLoop < intRetVal.Length; intInnerLoop++)
{
if (dblBestValue < udrPicBoxTrayElements[intRetVal[intInnerLoop]].trayLoc.y)
{
dblBestValue = udrPicBoxTrayElements[intRetVal[intInnerLoop]].trayLoc.y;
intBestIndex = intInnerLoop;
}
}
if (intBestIndex != intOuterLoop)
{
intTemp = intRetVal[intOuterLoop];
intRetVal[intOuterLoop] = intRetVal[intBestIndex];
intRetVal[intBestIndex] = intTemp;
}
}
return intRetVal;
}
public void repositionTray()
{
double dblDeltaAngle;
//lblTransparentLabel.Visible = false;
if (udrPicBoxTrayElements == null)
return;
else if (udrPicBoxTrayElements.Length == 0)
return;
// distribute pics around the circle evenly : set their respective angles around the circle
if (udrPicBoxTrayElements.Length - 1 > 0)
{
dblDeltaAngle = (2 * Math.PI) / (udrPicBoxTrayElements.Length);
for (int intPicBoxCounter = 0; intPicBoxCounter < udrPicBoxTrayElements.Length; intPicBoxCounter++)
udrPicBoxTrayElements[intPicBoxCounter].trayLoc.angle = Math.PI / 2 + intPicBoxCounter * dblDeltaAngle;
}
else
udrPicBoxTrayElements[0].trayLoc.angle = Math.PI / 2;
int intXSignOfSelectedPicBeforeMove = 0, intXSignOfSelectedPicAfterMove = 0;
try
{ intXSignOfSelectedPicBeforeMove = Math.Sign(udrPicBoxTrayElements[intSelected].trayLoc.x); }
catch (Exception)
{ }
// place on the cartesian plane using the radius of circle and each picture's angle + circle rotation angle
for (int intPicBoxCounter = 0; intPicBoxCounter < udrPicBoxTrayElements.Length; intPicBoxCounter++)
{
udrPicBoxTrayElements[intPicBoxCounter].trayLoc.x = Math.Cos(udrPicBoxTrayElements[intPicBoxCounter].trayLoc.angle + dblCurrentAngle - Math.PI / 2);
udrPicBoxTrayElements[intPicBoxCounter].trayLoc.y = Math.Sin(udrPicBoxTrayElements[intPicBoxCounter].trayLoc.angle + dblCurrentAngle - Math.PI / 2);
}
int[] intRankingIndices = getRankingIndices();
if (intRankingIndices == null)
return;
double dblMaxYReference = udrCenter.y + udrMaxSize.y;
udtCartesian udrCirclePt;
//create a ranking indice array to display them from back to front
for (int intPicCounter = 0; intPicCounter < intRankingIndices.Length; intPicCounter++)
{
/// - set their size accordingly (back is smaller, front is bigger)
double dblSizeAttenuationFactor; /// -1 is at the front, 1 is at the back
double dblDistanceToFront = 1 + udrPicBoxTrayElements[intRankingIndices[intPicCounter]].trayLoc.y;
// dblDistanceToFront ranges from 0(front) to 2(back)
double dblFactorRange = 1 - dblMinSizeFraction;
dblSizeAttenuationFactor = 1 - dblFactorRange * (dblDistanceToFront / 2);
resizePic(ref udrPicBoxTrayElements[intRankingIndices[intPicCounter]], attenuateUdtCartesian(udrMaxSize, dblSizeAttenuationFactor));
/// - place them on the form (left,top)
/// - center the x value of pic loc on circle Pt, place top of pic on circle Pt
udrCirclePt.x = udrCenter.x + dblCircleRadius * Math.Cos(udrPicBoxTrayElements[intRankingIndices[intPicCounter]].trayLoc.angle + dblCurrentAngle - Math.PI / 2);
udrCirclePt.y = udrCenter.y - dblCircleRadius * Math.Sin(udrPicBoxTrayElements[intRankingIndices[intPicCounter]].trayLoc.angle + dblCurrentAngle - Math.PI / 2);
udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Left = (int)(udrCirclePt.x - udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Width / 2);
udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.Top = (int)(udrCirclePt.y);
/// - bring to front (will be covered by those that follow)
udrPicBoxTrayElements[intRankingIndices[intPicCounter]].picBox.BringToFront();
}
try
{ picBackground.Refresh(); }
catch (Exception)
{ }
//try
//{
// // the transparent label allows the user to click on the label
// // and select an image using the transparentLabel's event handlers
// lblTransparentLabel.BringToFront();
// lblTransparentLabel.Refresh();
// lblTransparentLabel.Visible = true;
//}
//catch (Exception)
//{}
try
{ intXSignOfSelectedPicAfterMove = Math.Sign(udrPicBoxTrayElements[intSelected].trayLoc.x); }
catch (Exception)
{ }
// when the user's selection crosses the X-axis and is last in the ranking indice array then
// it is in front and rotation can stop
if (intSelected == intRankingIndices[intRankingIndices.Length - 1])
if (intXSignOfSelectedPicAfterMove != intXSignOfSelectedPicBeforeMove)
tmrRotate.Enabled = bolCarousel;
}
udtCartesian attenuateUdtCartesian(udtCartesian udrCar, double dblFactor)
{
udtCartesian udrRetVal = new udtCartesian();
udrRetVal.x = udrCar.x * dblFactor;
udrRetVal.y = udrCar.y * dblFactor;
return udrRetVal;
}
void resizePic(ref udtPicBoxTrayElement udrThisTrayElement, udtCartesian udrMaxDimensions)
{
double dblMDXOverY = udrMaxDimensions.x / udrMaxDimensions.y;
if (udrThisTrayElement.dblXOverYRatio > dblMDXOverY)
{ // width is limiting factor
udrThisTrayElement.picBox.Width = (int)udrMaxDimensions.x;
udrThisTrayElement.picBox.Height = (int)(udrThisTrayElement.picBox.Width / udrThisTrayElement.dblXOverYRatio);
}
else
{ // height is limiting factor
udrThisTrayElement.picBox.Height = (int)udrMaxDimensions.y;
udrThisTrayElement.picBox.Width = (int)(udrThisTrayElement.picBox.Height * udrThisTrayElement.dblXOverYRatio);
}
}
public void resetPicTray()
{
for (int intPicCounter = 0; intPicCounter < udrPicBoxTrayElements.Length; intPicCounter++)
{
udrPicBoxTrayElements[intPicCounter].picBox.Visible = false;
udrPicBoxTrayElements[intPicCounter].picBox.Dispose();
}
udrPicBoxTrayElements = null;
dblTurnAngleStep = Math.PI / 64;
dblMinSizeFraction = 0.5;
udrMaxSizeFraction.x = udrMaxSizeFraction.y = 0.45;
udrCenterFraction.x = 0.5;
udrCenterFraction.y = 0.3;
bolMouseMoveOverAutoSelect = false;
bolClickPicBool = false;
udrPicBoxTrayElements = null;
turningAngle = enuTurning.notTurning;
}
}
public class classPicBox : System.Windows.Forms.PictureBox
{
public int index;
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Christ Kennedy grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University. He is unemployable and currently living in Moncton, N.B. writing his next novel.