NavigationWidget.cs (5539B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // The Command & Conquer Map Editor and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // The Command & Conquer Map Editor and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 using MobiusEditor.Controls; 16 using MobiusEditor.Interface; 17 using MobiusEditor.Model; 18 using System; 19 using System.Drawing; 20 using System.Windows.Forms; 21 22 namespace MobiusEditor.Widgets 23 { 24 public class MouseCellChangedEventArgs : EventArgs 25 { 26 public Point OldCell { get; private set; } 27 28 public Point NewCell { get; private set; } 29 30 public MouseCellChangedEventArgs(Point oldCell, Point newCell) 31 { 32 OldCell = oldCell; 33 NewCell = newCell; 34 } 35 } 36 37 public class NavigationWidget : IWidget 38 { 39 private static readonly Pen defaultMouseoverPen = new Pen(Color.Yellow, 4); 40 41 private readonly MapPanel mapPanel; 42 private readonly Size cellSize; 43 44 private bool dragging = false; 45 private Point lastMouseLocation; 46 47 public CellMetrics Metrics { get; private set; } 48 49 public Point MouseCell { get; private set; } 50 public Point MouseSubPixel { get; private set; } 51 52 private Size mouseoverSize = new Size(1, 1); 53 public Size MouseoverSize 54 { 55 get => mouseoverSize; 56 set => mouseoverSize = !value.IsEmpty ? new Size(value.Width | 1, value.Height | 1) : Size.Empty; 57 } 58 59 public event EventHandler<MouseCellChangedEventArgs> MouseCellChanged; 60 61 public NavigationWidget(MapPanel mapPanel, CellMetrics metrics, Size cellSize) 62 { 63 this.mapPanel = mapPanel; 64 this.mapPanel.MouseDown += MapPanel_MouseDown; 65 this.mapPanel.MouseMove += MapPanel_MouseMove; 66 Metrics = metrics; 67 this.cellSize = cellSize; 68 } 69 70 public void Refresh() 71 { 72 OnMouseMove(mapPanel.PointToClient(Control.MousePosition)); 73 } 74 75 private void MapPanel_MouseDown(object sender, MouseEventArgs e) 76 { 77 if ((e.Button & MouseButtons.Middle) != MouseButtons.None) 78 { 79 lastMouseLocation = e.Location; 80 dragging = true; 81 } 82 } 83 84 private void MapPanel_MouseMove(object sender, MouseEventArgs e) 85 { 86 OnMouseMove(e.Location); 87 } 88 89 private void OnMouseMove(Point location) 90 { 91 if (dragging) 92 { 93 if ((Control.MouseButtons & MouseButtons.Middle) == MouseButtons.None) 94 { 95 dragging = false; 96 } 97 else 98 { 99 var delta = location - (Size)lastMouseLocation; 100 if (!delta.IsEmpty) 101 { 102 mapPanel.AutoScrollPosition = new Point(-mapPanel.AutoScrollPosition.X - delta.X, -mapPanel.AutoScrollPosition.Y - delta.Y); 103 } 104 } 105 } 106 107 lastMouseLocation = location; 108 109 var newMousePosition = mapPanel.ClientToMap(location); 110 MouseSubPixel = new Point( 111 (newMousePosition.X * Globals.PixelWidth / cellSize.Width) % Globals.PixelWidth, 112 (newMousePosition.Y * Globals.PixelHeight / cellSize.Height) % Globals.PixelHeight 113 ); 114 115 var newMouseCell = new Point(newMousePosition.X / cellSize.Width, newMousePosition.Y / cellSize.Height); 116 if (MouseCell == newMouseCell) 117 { 118 return; 119 } 120 121 if (!Metrics.Contains(newMouseCell)) 122 { 123 return; 124 } 125 126 var oldCell = MouseCell; 127 MouseCell = newMouseCell; 128 129 MouseCellChanged?.Invoke(this, new MouseCellChangedEventArgs(oldCell, MouseCell)); 130 131 mapPanel.Invalidate(); 132 } 133 134 public void Render(Graphics graphics) 135 { 136 if (!MouseoverSize.IsEmpty) 137 { 138 var rect = new Rectangle(new Point(MouseCell.X * cellSize.Width, MouseCell.Y * cellSize.Height), cellSize); 139 rect.Inflate(cellSize.Width * (MouseoverSize.Width / 2), cellSize.Height * (MouseoverSize.Height / 2)); 140 graphics.DrawRectangle(defaultMouseoverPen, rect); 141 } 142 } 143 144 #region IDisposable Support 145 private bool disposedValue = false; 146 147 protected virtual void Dispose(bool disposing) 148 { 149 if (!disposedValue) 150 { 151 if (disposing) 152 { 153 mapPanel.MouseDown -= MapPanel_MouseDown; 154 mapPanel.MouseMove -= MapPanel_MouseMove; 155 } 156 disposedValue = true; 157 } 158 } 159 160 public void Dispose() 161 { 162 Dispose(true); 163 } 164 #endregion 165 } 166 }