public FleetView() { InitializeComponent(); this.Paint += (s, e) => { var g = e.Graphics; var Width = this.Width - this.Padding.Left - this.Padding.Right; var Height = this.Height - this.Padding.Top - this.Padding.Bottom; g.TranslateTransform(this.Padding.Left, this.Padding.Top); IEnumerable <Ship> Ships = null; int nw = 0, y = 0; #region Draw Header using (SolidBrush b = new SolidBrush(Color.FromArgb(0x30, 0x90, 0x90, 0x90))) g.FillRectangle(b, new Rectangle(0, 0, Width, 24)); if (this.Fleet != null && this.Fleet.Ships != null) { int x = 4; FleetState state = this.Fleet.State; if (state != null) { string[] texts = new string[] { "레벨 합계: " + state.TotalLevel.ToString(), "평균: " + Math.Round(state.AverageLevel, 2).ToString(), "색적: " + Math.Round(state.ViewRange, 2).ToString(), string.Format( "제공: {0}-{1} ({2} %)", state.MinAirSuperiorityPotential.ToString(), state.MaxAirSuperiorityPotential.ToString(), Math.Round(state.EncounterPercent, 2) ), state.Speed.ToStateString() }; foreach (var text in texts) { Size sz = TextRenderer.MeasureText(text, this.Font); TextRenderer.DrawText(g, text, this.Font, new Rectangle(x, y + 5, sz.Width, sz.Height), Color.White); x += sz.Width + 8; } x -= 4; } nw = x; } y += 24 + 1; #endregion #region Draw Fleet Name using (SolidBrush b = new SolidBrush(Color.FromArgb(0x30, 0x90, 0x90, 0x90))) g.FillRectangle(b, new Rectangle(0, y, 30, Height - y)); using (SolidBrush b = new SolidBrush(Color.White)) { var FleetName = Fleet?.Name ?? "함대명"; using (Bitmap buffer = new Bitmap(30, Height - y, PixelFormat.Format32bppArgb)) { using (Graphics g2 = Graphics.FromImage(buffer)) { Size sz = TextRenderer.MeasureText(FleetName, this.Font); g2.TranslateTransform(-sz.Width / 2, -sz.Height / 2, MatrixOrder.Append); g2.RotateTransform(-90, MatrixOrder.Append); g2.TranslateTransform(15, (Height - y) / 2, MatrixOrder.Append); g2.DrawString(FleetName, this.Font, b, 0, 0); } g.DrawImage(buffer, new Rectangle(0, y, 30, Height - y)); } } #endregion if (this.Fleet == null || this.Fleet.Ships == null) { return; // No elements to draw } Ships = this.Fleet.Ships; if (Ships.Count() == 0) { return; } #region Draw Ships var w1 = TextRenderer.MeasureText("Lv.", new Font(this.Font.FontFamily, 9)).Width - 4; var w2 = TextRenderer.MeasureText("HP:", new Font(this.Font.FontFamily, 9)).Width - 6; var cells = new int[] { 0, 0, 0, 0 }; cells[0] = Ships.Max(x => TextRenderer.MeasureText(x.Info.ShipType.Name, new Font(this.Font.FontFamily, 8)).Width) + 4; cells[1] = Ships.Max(x => TextRenderer.MeasureText(x.Info.Name, new Font(this.Font.FontFamily, 15)).Width) + 4; cells[2] = w1 + Ships.Max(x => TextRenderer.MeasureText(x.Level.ToString(), new Font(this.Font.FontFamily, 10)).Width) + 8; cells[3] = w2 + Ships.Max(x => TextRenderer.MeasureText(x.HP.Current.ToString(), new Font(this.Font.FontFamily, 11)).Width - 8 + TextRenderer.MeasureText("/" + x.HP.Maximum.ToString(), new Font(this.Font.FontFamily, 9)).Width ) + 8; SlotItemMap.Clear(); foreach (var ship in Ships) { if (ship == null) { continue; } var x = 30; Size sz; #region 함종명 TextRenderer.DrawText( g, ship.Info.ShipType.Name, new Font(this.Font.FontFamily, 8), new Rectangle(x + 4, y - 3, cells[0], 28), Color.FromArgb(0x30, 0x90, 0x90, 0x90), TextFormatFlags.Right | TextFormatFlags.Bottom ); x += cells[0]; #endregion #region 함선명 TextRenderer.DrawText( g, ship.Info.Name, new Font(this.Font.FontFamily, 15), new Rectangle(x, y, cells[1], 28), Color.White, TextFormatFlags.Left | TextFormatFlags.Bottom ); x += cells[1]; #endregion #region 함선레벨 TextRenderer.DrawText( g, "Lv.", new Font(this.Font.FontFamily, 9), new Rectangle(x, y - 2, w1, 28), Color.FromArgb(0x30, 0x90, 0x90, 0x90), TextFormatFlags.Left | TextFormatFlags.Bottom ); TextRenderer.DrawText( g, ship.Level.ToString(), new Font(this.Font.FontFamily, 11), new Rectangle(x + w1, y - 1, cells[2] - w1, 28), Color.White, TextFormatFlags.Left | TextFormatFlags.Bottom ); x += cells[2]; #endregion #region 함선 체력 sz = TextRenderer.MeasureText(ship.HP.Current.ToString(), new Font(this.Font.FontFamily, 11)); TextRenderer.DrawText( g, "HP:", new Font(this.Font.FontFamily, 9), new Rectangle(x, y + 2, cells[1], 16), Color.FromArgb(0x30, 0x90, 0x90, 0x90), TextFormatFlags.Left | TextFormatFlags.Bottom ); TextRenderer.DrawText( g, ship.HP.Current.ToString(), new Font(this.Font.FontFamily, 11), new Rectangle(x + w2, y, cells[1], 16), Color.White, TextFormatFlags.Left | TextFormatFlags.Bottom ); TextRenderer.DrawText( g, "/" + ship.HP.Maximum.ToString(), new Font(this.Font.FontFamily, 9), new Rectangle(x + w2 + sz.Width - 8, y + 2, cells[1], 16), Color.FromArgb(0x30, 0x90, 0x90, 0x90), TextFormatFlags.Left | TextFormatFlags.Bottom ); DrawProgress(g, new Rectangle(x + 2, y + 20, cells[3] - 8 - 4, 6), ship.HP); x += cells[3]; #endregion #region 함선 피로도 using (SolidBrush b = new SolidBrush(GetCondColor(ship.ConditionType))) g.FillRectangle(b, new Rectangle(x + 4, y + 4, 12, 12)); TextRenderer.DrawText( g, ship.Condition.ToString(), new Font(this.Font.FontFamily, 9), new Rectangle(x + 16, y + 3, 24, 16), Color.White, TextFormatFlags.Left | TextFormatFlags.Top ); TextRenderer.DrawText( g, "피로도", new Font(this.Font.FontFamily, 7), new Rectangle(x + 2, y + 18, 40, 16), Color.FromArgb(0x30, 0x90, 0x90, 0x90), TextFormatFlags.Left | TextFormatFlags.Top ); x += 48; #endregion #region 함선 연료/탄약 DrawProgress(g, new Rectangle(x - 6, y + 6, 44, 6), ship.Fuel, 5); DrawProgress(g, new Rectangle(x - 6, y + 18, 44, 6), ship.Bull, 5); x += 44; #endregion #region 장비 foreach (var item in ship.Slots) { if (item == null || !item.Equipped) { continue; } SlotItemMap.Add(new Rectangle(x, y + 2, 36, 28), item); DrawSlotItem(g, item, x, y + 2); x += 38; } if (ship.ExSlotExists && ship.ExSlot.Equipped) { using (Pen p = new Pen(Color.FromArgb(0x90, 0x90, 0x90, 0x90))) g.DrawLine(p, x + 2, y + 2, x + 2, y + 28); x += 7; var item = ship.ExSlot; SlotItemMap.Add(new Rectangle(x, y + 2, 36, 28), item); DrawSlotItem(g, item, x, y + 2); x += 38; } x -= 2; #endregion nw = Math.Max(nw, x); y += 32; } #endregion for (var i = 0; i < Ships.Count(x => x != null); i++) { using (Pen p = new Pen(Color.FromArgb(0x30, 0x90, 0x90, 0x90))) g.DrawLine(p, 30, y - i * 32 - 1, nw, y - i * 32 - 1); } var ResultSize = new Size( nw + this.Padding.Left + this.Padding.Right, y + this.Padding.Top + this.Padding.Bottom ); if (ResultSize.Width != LatestSize.Width || ResultSize.Height != LatestSize.Height) { LatestSize = ResultSize; this.PerformAutoScale(); this.PerformLayout(); } }; this.MouseMove += (s, e) => { if (!this.SlotItemMap.Any(x => x.Key.Contains(e.X, e.Y))) { CurrentItem = null; toolTip.Hide(this); return; } var item = this.SlotItemMap.FirstOrDefault(x => x.Key.Contains(e.X, e.Y)).Value.Item; if (item == CurrentItem) { return; } CurrentItem = item; toolTip.Show(CurrentItem.NameWithLevel, this); }; this.MouseDown += (s, e) => { if (!this.SlotItemMap.Any(x => x.Key.Contains(e.X, e.Y))) { CurrentItem = null; toolTip.Hide(this); return; } var item = this.SlotItemMap.FirstOrDefault(x => x.Key.Contains(e.X, e.Y)).Value.Item; CurrentItem = item; toolTip.Show(CurrentItem.NameWithLevel, this); }; var toolTipFont = new Font(this.Font.FontFamily, 10); toolTip.Popup += (s, e) => { if (CurrentItem == null) { e.Cancel = true; return; } var sz = TextRenderer.MeasureText(CurrentItem.NameWithLevel, toolTipFont); e.ToolTipSize = new Size(sz.Width + 6, sz.Height + 6); }; toolTip.Draw += (s, e) => { var g = e.Graphics; g.Clear(Color.FromArgb(0x27, 0x27, 0x2F)); g.DrawRectangle( new Pen(Color.FromArgb(0x44, 0x44, 0x4A), 1.0f), new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Width - 1, e.Bounds.Height - 1) ); TextRenderer.DrawText( g, e.ToolTipText, toolTipFont, e.Bounds, Color.FromArgb(255, 255, 255), TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter ); }; }
public TableView(SlotitemListTable Owner) { // SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true); this.DoubleBuffered = true; this.Owner = Owner; this.Font = Owner?.Font; this.components = new System.ComponentModel.Container(); toolTip = new ToolTip(this.components); toolTip.OwnerDraw = true; this.Resize += (s, e) => this.RequestUpdate(); this.Paint += (s, e) => { var g = e.Graphics; var Width = this.Width - this.Padding.Left - this.Padding.Right; var Height = this.Height - this.Padding.Top - this.Padding.Bottom; g.Clear(this.BackColor); Font font8 = new Font(this.Font.FontFamily, 8); var Ships = homeport?.Organization?.Ships; var SlotItems = homeport?.Itemyard?.SlotItems.Select(_ => _.Value) .OrderBy(_ => _.Info.Id) .GroupBy(_ => _.Info.Id); #region Cell Size Calculate ColumnSizes[0] = SlotItems?.Count() > 0 ? (SlotItems?.Max(__ => __.Max(_ => TextRenderer.MeasureText(_.Info.Name.ToString(), this.Font).Width) ) ?? 0) + 20 : 0; ColumnSizes[1] = SlotItems?.Count() > 0 ? (SlotItems?.Max(_ => TextRenderer.MeasureText(_.Count().ToString(), this.Font).Width) ?? 0) : 0; ColumnSizes[2] = ColumnSizes[3] = ColumnSizes[4] = 0; ColumnSizes[0] = Math.Max(ColumnSizes[0], TextRenderer.MeasureText(Headers[0], this.Font).Width) + 8; ColumnSizes[1] = Math.Max(ColumnSizes[1], TextRenderer.MeasureText(Headers[1], this.Font).Width) + 8; ColumnSizes[2] = Math.Max(ColumnSizes[2], TextRenderer.MeasureText(Headers[2], this.Font).Width) + 8; ColumnSizes[3] = Math.Max(ColumnSizes[3], TextRenderer.MeasureText(Headers[3], this.Font).Width) + 8; ColumnSizes[4] = Math.Max(ColumnSizes[4], TextRenderer.MeasureText(Headers[4], this.Font).Width) + 8; ColumnSizes[5] = 0; ColumnSizes[5] = (this.Owner?.Width ?? this.Width) - ColumnSizes.Sum() - 1 - 18; #endregion int x, y = 0; using (Pen p = new Pen(Color.FromArgb(83, 83, 83), 1.0f)) { SlotItemMap.Clear(); #region Data Rendering if (SlotItems != null) { Color colorWhite = Color.White; Color colorDarkGray = Color.FromArgb(0x20, 0x90, 0x90, 0x90); Color colorGray = Color.FromArgb(0x40, 0xC4, 0xC4, 0xC4); Color colorLevel = Color.FromArgb(0x45, 0xA9, 0xA5); Color colorProficiency123 = Color.FromArgb(0x98, 0xB3, 0xCE); Color colorProficiency4567 = Color.FromArgb(0xD4, 0x9C, 0x0F); int idx = 0; y = 0; foreach (var slotitemIdGroup in SlotItems) { if (slotitemIdGroup == null) { continue; } int widthValue, nx; x = 0; y -= 2; var slotitemLevelGroup = slotitemIdGroup .GroupBy(_ => _.NameWithLevel); if (idx % 2 == 1) { int py = y; #region Calcuate Equipped Ships Size foreach (var slotitems in slotitemLevelGroup) { int nx2 = x; var EquippedShips = Ships.Where( _ => _.Value.Slots.Any(__ => slotitems.Any(___ => ___.Id == __.Item.Id)) || (slotitems.Any(___ => ___.Id == _.Value.ExSlot?.Item.Id)) ).Select(_ => _.Value); foreach (var ship in EquippedShips) { int sizeName = 0; int sizeLevel = 0; int sizeCount = 0; int hasCount = ship.Slots.Count(_ => slotitems.Any(__ => __.Id == _.Item.Id)) + (slotitems.Any(_ => _.Id == ship.ExSlot?.Item.Id) ? 1 : 0); sizeName = TextRenderer.MeasureText(ship.Info.Name, this.Font).Width - 2; sizeLevel = TextRenderer.MeasureText("Lv." + ship.Level.ToString(), font8).Width; if (hasCount > 1) { sizeCount = TextRenderer.MeasureText("x " + hasCount.ToString(), font8).Width + 1; } if ((x - nx2) + sizeName + sizeLevel + sizeCount > ColumnSizes[5]) { x = nx2; y += RowSize; } x += sizeName + sizeLevel + sizeCount + 8; } } #endregion using (SolidBrush b = new SolidBrush(Color.FromArgb(0x18, 0x90, 0x90, 0x90))) g.FillRectangle(b, new Rectangle(0, py, Width, y - py + RowSize)); x = 0; y = py; } #region Icon And Name Image icon = ImageAssets.GetSlotIconImage(slotitemIdGroup.First().Info.IconType); g.DrawImage(icon, new Rectangle(x + 4, y + 2, 18, 18)); TextRenderer.DrawText( g, slotitemIdGroup.First().Info.Name, this.Font, new Rectangle(x + 20 + 3, y, ColumnSizes[0] - 8, RowSize), colorWhite, TextFormatFlags.VerticalCenter | TextFormatFlags.Left ); SlotItemMap.Add(new Rectangle(x, y, ColumnSizes[0], RowSize), slotitemIdGroup.First()); x += ColumnSizes[0]; #endregion #region Items count (Group) TextRenderer.DrawText( g, slotitemIdGroup.Count().ToString(), this.Font, new Rectangle(x + 3, y, ColumnSizes[1] - 8, RowSize), colorWhite, TextFormatFlags.VerticalCenter | TextFormatFlags.Left ); x += ColumnSizes[1]; #endregion nx = x; foreach (var slotitems in slotitemLevelGroup) { if (slotitems == null) { continue; } var slotitem = slotitems.First(); #region Item Level TextRenderer.DrawText( g, "★" + (slotitem.Level == 10 ? "max" : "+" + slotitem.Level.ToString()), this.Font, new Rectangle(x + 3, y, ColumnSizes[2] - 8, RowSize), slotitem.Level > 0 ? colorLevel : colorDarkGray, TextFormatFlags.VerticalCenter | TextFormatFlags.Left ); x += ColumnSizes[2]; #endregion #region Item Proficiency TextRenderer.DrawText( g, "+" + slotitem.Proficiency.ToString(), this.Font, new Rectangle(x + 3, y, ColumnSizes[3] - 8, RowSize), slotitem.Proficiency >= 4 ? colorProficiency4567 : ( slotitem.Proficiency >= 1 && slotitem.Proficiency <= 3 ? colorProficiency123 : colorDarkGray ), TextFormatFlags.VerticalCenter | TextFormatFlags.Left ); x += ColumnSizes[3]; #endregion #region Items count widthValue = TextRenderer.MeasureText( slotitems.Count().ToString(), this.Font ).Width; TextRenderer.DrawText( g, slotitems.Count().ToString(), this.Font, new Rectangle(x + 3, y, ColumnSizes[4] - 8, RowSize), colorWhite, TextFormatFlags.VerticalCenter | TextFormatFlags.Left ); TextRenderer.DrawText( g, "(" + slotitems.Count( _ => !Ships.Any( __ => __.Value.Slots.Any(___ => ___.Item.Id == _.Id) || (__.Value.ExSlot?.Item.Id == _.Id) ) ) + ")", font8, new Rectangle(x + widthValue + 3, y, ColumnSizes[4] - 8, RowSize - 4), colorGray, TextFormatFlags.Bottom | TextFormatFlags.Left ); x += ColumnSizes[4]; #endregion #region Equipped Ships int nx2 = x; var EquippedShips = Ships.Where( _ => _.Value.Slots.Any(__ => slotitems.Any(___ => ___.Id == __.Item.Id)) || (slotitems.Any(___ => ___.Id == _.Value.ExSlot?.Item.Id)) ).Select(_ => _.Value); foreach (var ship in EquippedShips) { int sizeName = 0; int sizeLevel = 0; int sizeCount = 0; int hasCount = ship.Slots.Count(_ => slotitems.Any(__ => __.Id == _.Item.Id)) + (slotitems.Any(_ => _.Id == ship.ExSlot?.Item.Id) ? 1 : 0); sizeName = TextRenderer.MeasureText(ship.Info.Name, this.Font).Width - 2; sizeLevel = TextRenderer.MeasureText("Lv." + ship.Level.ToString(), font8).Width; if (hasCount > 1) { sizeCount = TextRenderer.MeasureText("x " + hasCount.ToString(), font8).Width + 1; } if ((x - nx2) + sizeName + sizeLevel + sizeCount > ColumnSizes[5]) { x = nx2; y += RowSize; } TextRenderer.DrawText(g, ship.Info.Name, this.Font, new Point(x, y + 4), colorWhite); TextRenderer.DrawText(g, "Lv." + ship.Level.ToString(), font8, new Point(x + sizeName, y + 4 + 2), colorGray); if (hasCount > 1) { using (SolidBrush b = new SolidBrush(Color.FromArgb(0x20, 0x20, 0x20))) g.FillRectangle(b, new Rectangle(x + sizeName + sizeLevel, y + 4, sizeCount, RowSize - 4 - 4)); TextRenderer.DrawText(g, "x " + hasCount.ToString(), font8, new Point(x + sizeName + sizeLevel + 1, y + 4 + 1), colorGray); } x += sizeName + sizeLevel + sizeCount + 8; } #endregion y += RowSize; x = nx; } // GroupBy LevelProficiency idx++; y += 3; g.DrawLine(p, 0, y - 3, Width, y - 3); } // GroupBy Id } #endregion } var ResultSize = new Size( ColumnSizes.Sum() + this.Padding.Left + this.Padding.Right + 1, y + this.Padding.Top + this.Padding.Bottom + 1 ); if (ResultSize.Width != LatestSize.Width || ResultSize.Height != LatestSize.Height) { LatestSize = ResultSize; this.PerformAutoScale(); this.PerformLayout(); this.Owner.RequestUpdate(); } }; var toolTipFont = new Font(this.Font.FontFamily, 10); toolTip.Popup += (s, e) => { if (CurrentItem == null) { e.Cancel = true; return; } var text = CurrentItem.Info.Name + Environment.NewLine + CurrentItem.Info.ToolTipData; var sz = TextRenderer.MeasureText(text, toolTipFont); e.ToolTipSize = new Size(sz.Width + 6, sz.Height + 6); }; toolTip.Draw += (s, e) => { var g = e.Graphics; g.Clear(Color.FromArgb(0x27, 0x27, 0x2F)); g.DrawRectangle( new Pen(Color.FromArgb(0x44, 0x44, 0x4A), 1.0f), new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Width - 1, e.Bounds.Height - 1) ); TextRenderer.DrawText( g, e.ToolTipText, toolTipFont, e.Bounds, Color.FromArgb(255, 255, 255), TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter ); }; this.MouseMove += (s, e) => { if (!this.SlotItemMap.Any(x => x.Key.Contains(e.X, e.Y))) { CurrentItem = null; toolTip.Hide(this); return; } var item = this.SlotItemMap.FirstOrDefault(x => x.Key.Contains(e.X, e.Y)).Value; if (item == CurrentItem) { return; } CurrentItem = item; toolTip.Show(CurrentItem.Info.Name + Environment.NewLine + CurrentItem.Info.ToolTipData, this); }; this.MouseDown += (s, e) => { if (!this.SlotItemMap.Any(x => x.Key.Contains(e.X, e.Y))) { CurrentItem = null; toolTip.Hide(this); return; } var item = this.SlotItemMap.FirstOrDefault(x => x.Key.Contains(e.X, e.Y)).Value; CurrentItem = item; toolTip.Show(CurrentItem.Info.Name + Environment.NewLine + CurrentItem.Info.ToolTipData, this); }; }