CnC_Remastered_Collection/CnCTDRAMapEditor/Widgets/NavigationWidget.cs
PG-SteveT e37e174be1 C&C Remastered Map Editor
Initial commit of C&C Remastered Map Editor code
2020-09-10 11:12:58 -07:00

167 lines
5.4 KiB
C#

//
// Copyright 2020 Electronic Arts Inc.
//
// The Command & Conquer Map Editor and corresponding source code is free
// software: you can redistribute it and/or modify it under the terms of
// the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
// The Command & Conquer Map Editor and corresponding source code is distributed
// in the hope that it will be useful, but with permitted additional restrictions
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
// distributed with this program. You should have received a copy of the
// GNU General Public License along with permitted additional restrictions
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
using MobiusEditor.Controls;
using MobiusEditor.Interface;
using MobiusEditor.Model;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MobiusEditor.Widgets
{
public class MouseCellChangedEventArgs : EventArgs
{
public Point OldCell { get; private set; }
public Point NewCell { get; private set; }
public MouseCellChangedEventArgs(Point oldCell, Point newCell)
{
OldCell = oldCell;
NewCell = newCell;
}
}
public class NavigationWidget : IWidget
{
private static readonly Pen defaultMouseoverPen = new Pen(Color.Yellow, 4);
private readonly MapPanel mapPanel;
private readonly Size cellSize;
private bool dragging = false;
private Point lastMouseLocation;
public CellMetrics Metrics { get; private set; }
public Point MouseCell { get; private set; }
public Point MouseSubPixel { get; private set; }
private Size mouseoverSize = new Size(1, 1);
public Size MouseoverSize
{
get => mouseoverSize;
set => mouseoverSize = !value.IsEmpty ? new Size(value.Width | 1, value.Height | 1) : Size.Empty;
}
public event EventHandler<MouseCellChangedEventArgs> MouseCellChanged;
public NavigationWidget(MapPanel mapPanel, CellMetrics metrics, Size cellSize)
{
this.mapPanel = mapPanel;
this.mapPanel.MouseDown += MapPanel_MouseDown;
this.mapPanel.MouseMove += MapPanel_MouseMove;
Metrics = metrics;
this.cellSize = cellSize;
}
public void Refresh()
{
OnMouseMove(mapPanel.PointToClient(Control.MousePosition));
}
private void MapPanel_MouseDown(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Middle) != MouseButtons.None)
{
lastMouseLocation = e.Location;
dragging = true;
}
}
private void MapPanel_MouseMove(object sender, MouseEventArgs e)
{
OnMouseMove(e.Location);
}
private void OnMouseMove(Point location)
{
if (dragging)
{
if ((Control.MouseButtons & MouseButtons.Middle) == MouseButtons.None)
{
dragging = false;
}
else
{
var delta = location - (Size)lastMouseLocation;
if (!delta.IsEmpty)
{
mapPanel.AutoScrollPosition = new Point(-mapPanel.AutoScrollPosition.X - delta.X, -mapPanel.AutoScrollPosition.Y - delta.Y);
}
}
}
lastMouseLocation = location;
var newMousePosition = mapPanel.ClientToMap(location);
MouseSubPixel = new Point(
(newMousePosition.X * Globals.PixelWidth / cellSize.Width) % Globals.PixelWidth,
(newMousePosition.Y * Globals.PixelHeight / cellSize.Height) % Globals.PixelHeight
);
var newMouseCell = new Point(newMousePosition.X / cellSize.Width, newMousePosition.Y / cellSize.Height);
if (MouseCell == newMouseCell)
{
return;
}
if (!Metrics.Contains(newMouseCell))
{
return;
}
var oldCell = MouseCell;
MouseCell = newMouseCell;
MouseCellChanged?.Invoke(this, new MouseCellChangedEventArgs(oldCell, MouseCell));
mapPanel.Invalidate();
}
public void Render(Graphics graphics)
{
if (!MouseoverSize.IsEmpty)
{
var rect = new Rectangle(new Point(MouseCell.X * cellSize.Width, MouseCell.Y * cellSize.Height), cellSize);
rect.Inflate(cellSize.Width * (MouseoverSize.Width / 2), cellSize.Height * (MouseoverSize.Height / 2));
graphics.DrawRectangle(defaultMouseoverPen, rect);
}
}
#region IDisposable Support
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
mapPanel.MouseDown -= MapPanel_MouseDown;
mapPanel.MouseMove -= MapPanel_MouseMove;
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
}