private int SelectedIndex = 0; //index de l'élément actuellement sélectionné private void DefineSelectedIndex(int newindex) { //make sure qu'il y a des élément. sinon on make sure que l'index actuel est 0 et que la caméra est à sa position de départ if (this.AnyElement) { int ni = newindex; //on check les bounds if (ni < 0) { ni = 0; } if (ni >= this.listElem.Count) { ni = this.listElem.Count - 1; } //on check s'il est différent de celui délà sélectionner if (ni != this.SelectedIndex) { this.SelectedIndex = ni; //on obtient l'élément et on lance le déplacement animé jusqu'à cet élément clElement elem = this.listElem[ni]; this.TargetPosition(elem.x, elem.angle); } } else //s'il n'y a aucun élément { this.SelectedIndex = 0; this.camX = 0d; this.camAngle = 0d; } }
private void Raise_ElementMouseDoubleClick(clElement elem, int index) { if (this.ElementMouseDoubleClick != null) { this.ElementMouseDoubleClick(this, new clElementEventArgs(elem, index)); } }
public clElement AddElement(string Text, object Tag) { //calcul la position du nouveau élément double x = 0d; double angle = 0d; if (this.listElem.Count > 0) { angle = this.listElem[this.listElem.Count - 1].angle + this.ItemSpace; x = this.listElem[this.listElem.Count - 1].x + this.GetMinimumDeltaX(); } //on fait calculer la largeur virtuel de la chaine de text, pour savoir quel deltax on doit appliquer à chaques prochains élément à être ajouté pour qu'après 1 tour, ils ne chevauchent pas le texte de l'élément actuel double VirtualTextWidth = this.GetVirtualTextWidth(Text); //on prend la largeur du texte et on la divise par le nombre d'élément qui fait 1 tour complet double MinimumDeltaX = VirtualTextWidth / (double)(this.FullTurnItemCount()) + 0.02d; //on ajoute le deltax minimum actuel à la liste des deltax minimum du dernier tour this.AddToLastDeltaX(MinimumDeltaX); //calcule la position horizontale de la fin du cylindre à droite double NewElementEnd = x + VirtualTextWidth + this.CylinderBorderWidth; if (NewElementEnd > this.VirtualRightEnd) { this.VirtualRightEnd = NewElementEnd; } clElement e = new clElement(Text, Tag, x, angle, VirtualTextWidth); this.listElem.Add(e); return(e); }
private void ImageBox_MouseDoubleClick(object sender, MouseEventArgs e) { //make sure que la souris n'est pas sur un control if (!this.IsMouseOnAnyControl()) { //make sure qu'il y a des élément if (this.AnyElement) { //on récupère l'élément et raise l'event clElement elem = this.listElem[this.SelectedIndex]; this.Raise_ElementMouseDoubleClick(elem, this.SelectedIndex); } } }
public void Refresh() { int imgWidth = this.Width; int imgHeight = this.Height; if (imgWidth < 100) { imgWidth = 100; } if (imgHeight < 100) { imgHeight = 100; } Bitmap img = new Bitmap(imgWidth, imgHeight); Graphics g = Graphics.FromImage(img); g.Clear(Color.White); double MulFactor = (double)imgHeight / 2d / this.ViewAngle; //ces 2 valeurs sont utilisées pour effectuer une rotation des coordonnés sur le cylindre double coss = Math.Cos(this.camAngle); double sinn = Math.Sin(this.camAngle); ////dessine le cylindre int uicTopSpace = (int)((this.ViewAngle - (1d / this.camZ)) * MulFactor); //espacement verticale entre le cylindre et les bords de l'image en haut et en bas int uicHeight = imgHeight - uicTopSpace - uicTopSpace; //hauteur graphique du cylindre //position graphique de la gauche du cylindre int uicLeft = (imgWidth / 2) - (int)((this.CylinderBorderWidth + this.camX) / this.camZ * MulFactor); if (uicLeft < 0) { uicLeft = 0; } //position graphique de la droite du cylindre int uicRight = (imgWidth / 2) + (int)((this.VirtualRightEnd - this.camX) / this.camZ * MulFactor); //dessine le corps principale du cylindre g.FillRectangle(this.CylinderBrush, uicLeft, uicTopSpace, uicRight - uicLeft, uicHeight); //dessine le bord gauche s'il le faut if (uicLeft > 0) { //calcule la position graphique du bord gauche, mais la position du cercle qui est la plus proche de la caméra int uicCloseLeft = (imgWidth / 2) - (int)((this.CylinderBorderWidth + this.camX) / (this.camZ - 1d) * MulFactor); g.FillEllipse(this.CylinderBrush, uicCloseLeft, uicTopSpace, 2 * (uicLeft - uicCloseLeft), uicHeight); } //dessine le bord droit s'il le faut if (uicRight < imgWidth) { //calcule la position graphique du bord droit, mais la position du cercle qui est la plus proche de la caméra int uicCloseRight = (imgWidth / 2) + (int)((this.VirtualRightEnd - this.camX) / (this.camZ - 1d) * MulFactor); g.FillEllipse(this.CylinderBrush, 2 * uicRight - uicCloseRight, uicTopSpace, 2 * (uicCloseRight - uicRight), uicHeight); } //si l'élément actuellement sélectionné est dans l'image (ca devrait être presque toujours le cas), cette variable sera true et le p3d2d sera gardé dans l'autre variable bool SelectedElemFound = false; //devient true si l'élément actuel est dans l'image clElement SelectedElem = null; p3d2d SelectedPos = new p3d2d(0, 0); double minimumZ = this.ViewAngle; // coordonné z+ minimum pour qu'un point de la surface du cylindre soit sur la face visible par la caméra ////dessine les élément int index = 0; while (index < this.listElem.Count) { clElement elem = this.listElem[index]; //on doit d'abord obtenir ses coordonnés réel. double elemX = elem.x; double elemY = -Math.Sin(elem.angle); double elemZ = Math.Cos(elem.angle); //maintenant on obtien ses coordonnés relatives à la caméra p3d2d relpos = this.convVirtualToUI(elemX, elemY, elemZ, imgWidth, imgHeight, coss, sinn); double dist = this.camZ - relpos.z; //check s'il sort de l'écran. si c'est le cas, on peut arrêter car tout les suivant seront eux aussi dehors de l'image if (relpos.uix > imgWidth) { break; } //check si l'item est actuellement visible à l'écran en vérifiant si le côté droit du texte est dans l'image int uiWidth = (int)(elem.VirtualTextWidth / dist * MulFactor); if (relpos.uix + uiWidth >= 0) { //si on est sur l'élément sélectionné par l'user, on le garde de côté if (index == this.SelectedIndex) { SelectedElemFound = true; SelectedElem = elem; SelectedPos = relpos; } //on check si l'élément est du côté visible du cylindre if (relpos.z > minimumZ) { //on calcul l'applatissement verticale du text. float TextYScale = (float)(relpos.z); //on calcule le height que la font doit avoir Font elemFont = new Font(this.uiFontName, (float)((double)imgHeight * this.uiCloseFontMulFactor * (this.camZ - 1d) / dist)); //on calcule la taille graphique qu'aura le text SizeF elemTextSize = g.MeasureString(elem.Text, elemFont); //on dessine le text de l'élément, centré verticalement g.TranslateTransform((float)(relpos.uix), (float)(relpos.uiy) - (elemTextSize.Height * TextYScale / 2f)); g.ScaleTransform(1f, TextYScale); g.DrawString(elem.Text, elemFont, Brushes.Black, 0f, 0f); g.ResetTransform(); //g.DrawString(elem.Text, elemFont, Brushes.Black, (float)(relpos.uix), (float)(relpos.uiy) - (elemTextSize.Height / 2f)); elemFont.Dispose(); } } //next iteration index++; } //si l'élément actuellement sélectionné a été rencontré, on dessine la flèche bleu à côté if (SelectedElemFound) { //make sure que l'élément actuel est sur la face visible if (SelectedPos.z > minimumZ) { int arrowHeight = (int)((double)(this.imgArrow.Height) * SelectedPos.z); if (arrowHeight >= this.imgArrow.Height - 5) { arrowHeight = this.imgArrow.Height; } g.DrawImage(this.imgArrow, SelectedPos.uix - 3 - this.imgArrow.Width, SelectedPos.uiy - (arrowHeight / 2), this.imgArrow.Width, arrowHeight); } } ////dessine les composant de l'interface graphique foreach (uiButton b in this.listButton) { Brush BackBrush = Brushes.Silver; if (b.IsMouseLeftDown) { BackBrush = Brushes.White; } g.FillRectangle(BackBrush, b.rec); g.DrawRectangle(Pens.Black, b.rec); //dessine le text du button, au milieux SizeF btnTextSizeF = g.MeasureString(b.Text, this.uiBtnFont); g.DrawString(b.Text, this.uiBtnFont, Brushes.Black, (float)(b.Left + (b.Width / 2)) - (btnTextSizeF.Width / 2f), (float)(b.Top + (b.Height / 2)) - (btnTextSizeF.Height / 2f)); } g.Dispose(); if (this.ImageBox.Image != null) { this.ImageBox.Image.Dispose(); } this.ImageBox.Image = img; this.ImageBox.Refresh(); }
public clElementEventArgs(clElement sElem, int sindex) { this.Elem = sElem; this.index = sindex; }