BizHawk/BizHawk.Client.EmuHawk/tools/CDL.cs

596 lines
15 KiB
C#
Raw Normal View History

2017-04-15 19:53:02 +00:00
using System;
using System.IO;
using System.Windows.Forms;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.ToolExtensions;
using BizHawk.Common.PathExtensions;
2017-04-15 19:53:02 +00:00
2020-02-28 19:09:05 +00:00
// TODO - select which memorydomains go out to the CDL file. will this cause a problem when re-importing it?
// perhaps missing domains shouldn't fail a check
// OR - just add a contextmenu option to the ListView item that selects it for export.
// TODO - add a contextmenu option which warps to the HexEditor with the provided domain selected for visualizing on the hex editor.
// TODO - consider setting colors for columns in CDL
// TODO - option to print domain name in caption instead of 0x01 etc.
// TODO - context menu should have copy option too
2017-04-15 19:53:02 +00:00
namespace BizHawk.Client.EmuHawk
{
public partial class CDL : ToolFormBase, IToolFormAutoConfig
{
2019-12-22 17:13:53 +00:00
private RecentFiles _recentFld = new RecentFiles();
2017-04-15 19:53:02 +00:00
[ConfigPersist]
private RecentFiles _recent
{
2019-12-22 17:13:53 +00:00
get => _recentFld;
set => _recentFld = value;
2017-04-15 19:53:02 +00:00
}
[ConfigPersist]
private bool CDLAutoSave { get; set; } = true;
[ConfigPersist]
private bool CDLAutoStart { get; set; } = true;
[ConfigPersist]
private bool CDLAutoResume { get; set; } = true;
private void SetCurrentFilename(string fname)
2017-04-15 19:53:02 +00:00
{
_currentFilename = fname;
Text = _currentFilename == null
? "Code Data Logger"
: $"Code Data Logger - {fname}";
2017-04-15 19:53:02 +00:00
}
[RequiredService]
private IMemoryDomains MemoryDomains { get; set; }
[RequiredService]
private ICodeDataLogger CodeDataLogger { get; set; }
2019-12-22 17:13:53 +00:00
private string _currentFilename;
2017-04-15 19:53:02 +00:00
private CodeDataLog _cdl;
public CDL()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
InitializeComponent();
tsbViewStyle.SelectedIndex = 0;
2019-10-19 20:21:45 +00:00
lvCDL.AllColumns.Clear();
lvCDL.AllColumns.AddRange(new []
{
new RollColumn { Name = "CDLFile", Text = "CDL File @", UnscaledWidth = 107, Type = ColumnType.Text },
new RollColumn { Name = "Domain", Text = "Domain", UnscaledWidth = 126, Type = ColumnType.Text },
new RollColumn { Name = "Percent", Text = "%", UnscaledWidth = 58, Type = ColumnType.Text },
new RollColumn { Name = "Mapped", Text = "Mapped", UnscaledWidth = 64, Type = ColumnType.Text },
new RollColumn { Name = "Size", Text = "Size", UnscaledWidth = 112, Type = ColumnType.Text },
new RollColumn { Name = "0x01", Text = "0x01", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x02", Text = "0x02", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x04", Text = "0x04", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x08", Text = "0x08", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x10", Text = "0x10", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x20", Text = "0x20", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x40", Text = "0x40", UnscaledWidth = 56, Type = ColumnType.Text },
new RollColumn { Name = "0x80", Text = "0x80", UnscaledWidth = 56, Type = ColumnType.Text }
2019-10-19 20:21:45 +00:00
});
2017-04-15 19:53:02 +00:00
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
UpdateDisplay(false);
}
public void FastUpdate()
{
// Do nothing
}
public void Restart()
{
//don't try to recover the current CDL!
//even though it seems like it might be nice, it might get mixed up between games. even if we use CheckCDL. Switching games with the same memory map will be bad.
_cdl = null;
SetCurrentFilename(null);
SetLoggingActiveCheck(false);
UpdateDisplay(true);
}
2019-12-22 17:13:53 +00:00
private void SetLoggingActiveCheck(bool value)
2017-04-15 19:53:02 +00:00
{
tsbLoggingActive.Checked = value;
}
2019-12-22 17:13:53 +00:00
private string[][] _listContents = new string[0][];
2017-04-15 19:53:02 +00:00
private void UpdateDisplay(bool force)
{
if (!tsbViewUpdate.Checked && !force)
return;
if (_cdl == null)
{
2019-10-19 20:21:45 +00:00
lvCDL.DeselectAll();
2017-04-15 19:53:02 +00:00
return;
}
2019-12-22 17:13:53 +00:00
_listContents = new string[_cdl.Count][];
2017-04-15 19:53:02 +00:00
int idx = 0;
foreach (var kvp in _cdl)
{
int[] totals = new int[8];
int total = 0;
unsafe
{
int* map = stackalloc int[256];
for (int i = 0; i < 256; i++)
map[i] = 0;
fixed (byte* data = kvp.Value)
{
byte* src = data;
byte* end = data + kvp.Value.Length;
while (src < end)
{
byte s = *src++;
map[s]++;
}
}
for (int i = 0; i < 256; i++)
{
if(i!=0) total += map[i];
if ((i & 0x01) != 0) totals[0] += map[i];
if ((i & 0x02) != 0) totals[1] += map[i];
if ((i & 0x04) != 0) totals[2] += map[i];
if ((i & 0x08) != 0) totals[3] += map[i];
if ((i & 0x10) != 0) totals[4] += map[i];
if ((i & 0x20) != 0) totals[5] += map[i];
if ((i & 0x40) != 0) totals[6] += map[i];
if ((i & 0x80) != 0) totals[7] += map[i];
}
}
var bm = _cdl.GetBlockMap();
long addr = bm[kvp.Key];
2019-12-22 17:13:53 +00:00
var lvi = _listContents[idx++] = new string[13];
2019-03-18 14:06:37 +00:00
lvi[0] = $"{addr:X8}";
2017-04-15 19:53:02 +00:00
lvi[1] = kvp.Key;
2019-03-18 14:06:37 +00:00
lvi[2] = $"{total / (float)kvp.Value.Length * 100f:0.00}%";
2017-04-15 19:53:02 +00:00
if (tsbViewStyle.SelectedIndex == 2)
2019-03-18 14:06:37 +00:00
lvi[3] = $"{total / 1024.0f:0.00}";
2017-04-15 19:53:02 +00:00
else
2019-03-18 14:06:37 +00:00
lvi[3] = $"{total}";
2017-04-15 19:53:02 +00:00
if (tsbViewStyle.SelectedIndex == 2)
{
int n = (int)(kvp.Value.Length / 1024.0f);
float ncheck = kvp.Value.Length / 1024.0f;
2019-03-18 14:06:37 +00:00
lvi[4] = $"of {(n == ncheck ? "" : "~")}{n} KBytes";
2017-04-15 19:53:02 +00:00
}
else
2019-03-18 14:06:37 +00:00
lvi[4] = $"of {kvp.Value.Length} Bytes";
2017-04-15 19:53:02 +00:00
for (int i = 0; i < 8; i++)
{
2017-04-15 20:37:30 +00:00
if (tsbViewStyle.SelectedIndex == 0)
2019-03-18 14:06:37 +00:00
lvi[5 + i] = $"{totals[i] / (float)kvp.Value.Length * 100f:0.00}%";
2017-04-15 20:37:30 +00:00
if (tsbViewStyle.SelectedIndex == 1)
2019-03-18 14:06:37 +00:00
lvi[5 + i] = $"{totals[i]}";
2017-04-15 20:37:30 +00:00
if (tsbViewStyle.SelectedIndex == 2)
2019-03-18 14:06:37 +00:00
lvi[5 + i] = $"{totals[i] / 1024.0f:0.00}";
2017-04-15 19:53:02 +00:00
}
}
2019-10-19 20:21:45 +00:00
lvCDL.RowCount = _cdl.Count;
2017-04-15 19:53:02 +00:00
}
public bool AskSaveChanges()
{
// nothing to fear:
if (_cdl == null)
return true;
// try auto-saving if appropriate
if (CDLAutoSave)
{
2018-11-13 08:21:19 +00:00
if (_currentFilename != null)
{
RunSave();
ShutdownCDL();
return true;
}
}
// TODO - I don't like this system. It's hard to figure out how to use it. It should be done in multiple passes.
var result = MessageBox.Show("Save changes to CDL session?", "CDL Auto Save", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No)
{
ShutdownCDL();
return true;
}
if (string.IsNullOrWhiteSpace(_currentFilename))
{
if (RunSaveAs())
2018-11-12 23:12:00 +00:00
{
ShutdownCDL();
return true;
2018-11-12 23:12:00 +00:00
}
ShutdownCDL();
return false;
}
2017-04-15 19:53:02 +00:00
RunSave();
ShutdownCDL();
return true;
2017-04-15 19:53:02 +00:00
}
public bool UpdateBefore => false;
2019-12-22 17:13:53 +00:00
private bool _autoloading;
2017-04-15 19:53:02 +00:00
public void LoadFile(string path)
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
var newCDL = new CodeDataLog();
newCDL.Load(fs);
//have the core create a CodeDataLog to check mapping information against
var testCDL = new CodeDataLog();
CodeDataLogger.NewCDL(testCDL);
if (!newCDL.Check(testCDL))
{
2019-12-22 17:13:53 +00:00
if(!_autoloading)
MessageBox.Show(this, "CDL file does not match emulator's current memory map!");
2017-04-15 19:53:02 +00:00
return;
}
//ok, it's all good:
_cdl = newCDL;
CodeDataLogger.SetCDL(null);
if (tsbLoggingActive.Checked || CDLAutoStart)
{
tsbLoggingActive.Checked = true;
2017-04-15 19:53:02 +00:00
CodeDataLogger.SetCDL(_cdl);
}
2017-04-15 19:53:02 +00:00
SetCurrentFilename(path);
}
UpdateDisplay(true);
}
private void FileSubMenu_DropDownOpened(object sender, EventArgs e)
{
SaveMenuItem.Enabled = _currentFilename != null;
SaveAsMenuItem.Enabled =
AppendMenuItem.Enabled =
ClearMenuItem.Enabled =
DisassembleMenuItem.Enabled =
_cdl != null;
miAutoSave.Checked = CDLAutoSave;
miAutoStart.Checked = CDLAutoStart;
miAutoResume.Checked = CDLAutoResume;
2017-04-15 19:53:02 +00:00
}
private void RecentSubMenu_DropDownOpened(object sender, EventArgs e)
{
RecentSubMenu.DropDownItems.Clear();
2020-01-12 15:54:15 +00:00
RecentSubMenu.DropDownItems.AddRange(_recent.RecentMenu(LoadFile, "Session"));
2017-04-15 19:53:02 +00:00
}
void NewFileLogic()
{
_cdl = new CodeDataLog();
CodeDataLogger.NewCDL(_cdl);
if (tsbLoggingActive.Checked || CDLAutoStart)
2017-04-15 19:53:02 +00:00
CodeDataLogger.SetCDL(_cdl);
else CodeDataLogger.SetCDL(null);
SetCurrentFilename(null);
UpdateDisplay(true);
}
private void NewMenuItem_Click(object sender, EventArgs e)
{
//take care not to clobber an existing CDL
if (_cdl != null)
{
var result = MessageBox.Show(this, "OK to create new CDL?", "Query", MessageBoxButtons.YesNo);
if (result != DialogResult.Yes)
return;
}
NewFileLogic();
}
private void OpenMenuItem_Click(object sender, EventArgs e)
{
var file = OpenFileDialog(
_currentFilename,
Remove PathManager code that had dependencies on Globals (#1881) * move one usage of Firwmare method into Firmware config where it is better suited * PathManager - remove unused code * move some PathEntry specific logic out of PathManger and into PathEntryCollection extension methods * PathManager - detangle some exe pathing logic from Global.Config usage, clarify what a completely broken method should actuall do * move more logic from PathManager to PathEntryCollection extension method * move absolute path creation to PathEntryCollection, lots of refactoring and simplifying of PathEntries usage * simplify PathEntryColleciton usage more * simplify PathEntryCollection more * break PathEntry classes into separate files, a bit of cleanup * move Rom path logic out of PathManager into PathEntryCollectionExtensions * move config UseRecentForRoms and LastRomPath into PathEntries, note that this is a breaking change for previous configs, those values will revert back to default values * move SaveRamPath logic from PathManager to PathEntryCollections * move cheats path logic from PathManager to PathEntryCollection * move another method out of PathManager * move some Retro hacks to PathEntryCollections, exposes more implicit dependencies * move savestate logic out of PathManager to PathEntryCollection * move more logic out of PathManager * move some savestate logic out of PathManager, move most to MainForm where it is used, detangle some implicit dependencies from SaveSlotManager * rename method * move more logic from PathManager to PathCollectionEntry * movie final Global.Config.PathEntries logic out of PathManager and into PathEnties
2020-03-15 20:12:36 +00:00
Config.PathEntries.LogAbsolutePath(),
2017-04-15 19:53:02 +00:00
"Code Data Logger Files",
"cdl");
if (file == null)
return;
//take care not to clobber an existing CDL
if (_cdl != null)
{
var result = MessageBox.Show(this, "OK to load new CDL?", "Query", MessageBoxButtons.YesNo);
if (result != DialogResult.Yes)
return;
}
LoadFile(file.FullName);
}
void RunSave()
{
_recent.Add(_currentFilename);
using var fs = new FileStream(_currentFilename, FileMode.Create, FileAccess.Write);
_cdl.Save(fs);
2017-04-15 19:53:02 +00:00
}
private void SaveMenuItem_Click(object sender, EventArgs e)
{
if (_cdl == null)
{
MessageBox.Show(this, "Cannot save with no CDL loaded!", "Alert");
return;
}
2017-04-15 19:53:02 +00:00
if (string.IsNullOrWhiteSpace(_currentFilename))
{
RunSaveAs();
return;
}
RunSave();
}
/// <summary>
/// returns false if the operation was canceled
/// </summary>
2017-04-15 19:53:02 +00:00
bool RunSaveAs()
{
var file = SaveFileDialog(
_currentFilename,
Remove PathManager code that had dependencies on Globals (#1881) * move one usage of Firwmare method into Firmware config where it is better suited * PathManager - remove unused code * move some PathEntry specific logic out of PathManger and into PathEntryCollection extension methods * PathManager - detangle some exe pathing logic from Global.Config usage, clarify what a completely broken method should actuall do * move more logic from PathManager to PathEntryCollection extension method * move absolute path creation to PathEntryCollection, lots of refactoring and simplifying of PathEntries usage * simplify PathEntryColleciton usage more * simplify PathEntryCollection more * break PathEntry classes into separate files, a bit of cleanup * move Rom path logic out of PathManager into PathEntryCollectionExtensions * move config UseRecentForRoms and LastRomPath into PathEntries, note that this is a breaking change for previous configs, those values will revert back to default values * move SaveRamPath logic from PathManager to PathEntryCollections * move cheats path logic from PathManager to PathEntryCollection * move another method out of PathManager * move some Retro hacks to PathEntryCollections, exposes more implicit dependencies * move savestate logic out of PathManager to PathEntryCollection * move more logic out of PathManager * move some savestate logic out of PathManager, move most to MainForm where it is used, detangle some implicit dependencies from SaveSlotManager * rename method * move more logic from PathManager to PathCollectionEntry * movie final Global.Config.PathEntries logic out of PathManager and into PathEnties
2020-03-15 20:12:36 +00:00
Config.PathEntries.LogAbsolutePath(),
2017-04-15 19:53:02 +00:00
"Code Data Logger Files",
"cdl");
if (file == null)
2017-04-15 19:53:02 +00:00
return false;
SetCurrentFilename(file.FullName);
2017-04-15 19:53:02 +00:00
RunSave();
return true;
}
private void SaveAsMenuItem_Click(object sender, EventArgs e)
{
RunSaveAs();
}
private void AppendMenuItem_Click(object sender, EventArgs e)
{
if (_cdl == null)
{
MessageBox.Show(this, "Cannot append with no CDL loaded!", "Alert");
}
else
{
Remove PathManager code that had dependencies on Globals (#1881) * move one usage of Firwmare method into Firmware config where it is better suited * PathManager - remove unused code * move some PathEntry specific logic out of PathManger and into PathEntryCollection extension methods * PathManager - detangle some exe pathing logic from Global.Config usage, clarify what a completely broken method should actuall do * move more logic from PathManager to PathEntryCollection extension method * move absolute path creation to PathEntryCollection, lots of refactoring and simplifying of PathEntries usage * simplify PathEntryColleciton usage more * simplify PathEntryCollection more * break PathEntry classes into separate files, a bit of cleanup * move Rom path logic out of PathManager into PathEntryCollectionExtensions * move config UseRecentForRoms and LastRomPath into PathEntries, note that this is a breaking change for previous configs, those values will revert back to default values * move SaveRamPath logic from PathManager to PathEntryCollections * move cheats path logic from PathManager to PathEntryCollection * move another method out of PathManager * move some Retro hacks to PathEntryCollections, exposes more implicit dependencies * move savestate logic out of PathManager to PathEntryCollection * move more logic out of PathManager * move some savestate logic out of PathManager, move most to MainForm where it is used, detangle some implicit dependencies from SaveSlotManager * rename method * move more logic from PathManager to PathCollectionEntry * movie final Global.Config.PathEntries logic out of PathManager and into PathEnties
2020-03-15 20:12:36 +00:00
var file = OpenFileDialog(
2017-04-15 19:53:02 +00:00
_currentFilename,
Remove PathManager code that had dependencies on Globals (#1881) * move one usage of Firwmare method into Firmware config where it is better suited * PathManager - remove unused code * move some PathEntry specific logic out of PathManger and into PathEntryCollection extension methods * PathManager - detangle some exe pathing logic from Global.Config usage, clarify what a completely broken method should actuall do * move more logic from PathManager to PathEntryCollection extension method * move absolute path creation to PathEntryCollection, lots of refactoring and simplifying of PathEntries usage * simplify PathEntryColleciton usage more * simplify PathEntryCollection more * break PathEntry classes into separate files, a bit of cleanup * move Rom path logic out of PathManager into PathEntryCollectionExtensions * move config UseRecentForRoms and LastRomPath into PathEntries, note that this is a breaking change for previous configs, those values will revert back to default values * move SaveRamPath logic from PathManager to PathEntryCollections * move cheats path logic from PathManager to PathEntryCollection * move another method out of PathManager * move some Retro hacks to PathEntryCollections, exposes more implicit dependencies * move savestate logic out of PathManager to PathEntryCollection * move more logic out of PathManager * move some savestate logic out of PathManager, move most to MainForm where it is used, detangle some implicit dependencies from SaveSlotManager * rename method * move more logic from PathManager to PathCollectionEntry * movie final Global.Config.PathEntries logic out of PathManager and into PathEnties
2020-03-15 20:12:36 +00:00
Config.PathEntries.LogAbsolutePath(),
2017-04-15 19:53:02 +00:00
"Code Data Logger Files",
"cdl");
if (file != null)
{
using var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
var newCDL = new CodeDataLog();
newCDL.Load(fs);
if (!_cdl.Check(newCDL))
2017-04-15 19:53:02 +00:00
{
MessageBox.Show(this, "CDL file does not match emulator's current memory map!");
return;
2017-04-15 19:53:02 +00:00
}
_cdl.LogicalOrFrom(newCDL);
UpdateDisplay(true);
2017-04-15 19:53:02 +00:00
}
}
}
private void ClearMenuItem_Click(object sender, EventArgs e)
{
if (_cdl == null)
{
MessageBox.Show(this, "Cannot clear with no CDL loaded!", "Alert");
}
else
{
var result = MessageBox.Show(this, "OK to clear CDL?", "Query", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
_cdl.ClearData();
UpdateDisplay(true);
}
}
}
private void DisassembleMenuItem_Click(object sender, EventArgs e)
{
if (_cdl == null)
{
MessageBox.Show(this, "Cannot disassemble with no CDL loaded!", "Alert");
return;
}
2019-11-02 04:29:09 +00:00
using var sfd = new SaveFileDialog();
2017-04-15 19:53:02 +00:00
var result = sfd.ShowDialog(this);
if (result == DialogResult.OK)
{
using var fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write);
CodeDataLogger.DisassembleCDL(fs, _cdl);
2017-04-15 19:53:02 +00:00
}
}
private void ExitMenuItem_Click(object sender, EventArgs e)
{
ShutdownCDL();
2017-04-15 19:53:02 +00:00
Close();
}
void ShutdownCDL()
{
_cdl = null;
CodeDataLogger.SetCDL(null);
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (!AskSaveChanges())
e.Cancel = true;
base.OnClosing(e);
}
protected override void OnShown(EventArgs e)
{
if (CDLAutoStart)
{
if (_cdl == null)
NewFileLogic();
}
base.OnShown(e);
2017-04-15 19:53:02 +00:00
}
protected override void OnClosed(EventArgs e)
{
CodeDataLogger?.SetCDL(null);
2017-04-15 19:53:02 +00:00
}
private void CDL_Load(object sender, EventArgs e)
2017-04-15 19:53:02 +00:00
{
if (CDLAutoResume)
{
try
{
2019-12-22 17:13:53 +00:00
_autoloading = true;
var autoResumeFile = $"{Global.Game.FilesystemSafeName()}.cdl";
Remove PathManager code that had dependencies on Globals (#1881) * move one usage of Firwmare method into Firmware config where it is better suited * PathManager - remove unused code * move some PathEntry specific logic out of PathManger and into PathEntryCollection extension methods * PathManager - detangle some exe pathing logic from Global.Config usage, clarify what a completely broken method should actuall do * move more logic from PathManager to PathEntryCollection extension method * move absolute path creation to PathEntryCollection, lots of refactoring and simplifying of PathEntries usage * simplify PathEntryColleciton usage more * simplify PathEntryCollection more * break PathEntry classes into separate files, a bit of cleanup * move Rom path logic out of PathManager into PathEntryCollectionExtensions * move config UseRecentForRoms and LastRomPath into PathEntries, note that this is a breaking change for previous configs, those values will revert back to default values * move SaveRamPath logic from PathManager to PathEntryCollections * move cheats path logic from PathManager to PathEntryCollection * move another method out of PathManager * move some Retro hacks to PathEntryCollections, exposes more implicit dependencies * move savestate logic out of PathManager to PathEntryCollection * move more logic out of PathManager * move some savestate logic out of PathManager, move most to MainForm where it is used, detangle some implicit dependencies from SaveSlotManager * rename method * move more logic from PathManager to PathCollectionEntry * movie final Global.Config.PathEntries logic out of PathManager and into PathEnties
2020-03-15 20:12:36 +00:00
var autoResumeDir = Config.PathEntries.LogAbsolutePath();
2019-12-22 17:13:53 +00:00
var autoResumePath = Path.Combine(autoResumeDir, autoResumeFile);
if (File.Exists(autoResumePath))
{
LoadFile(autoResumePath);
}
}
finally
{
2019-12-22 17:13:53 +00:00
_autoloading = false;
}
}
2019-12-22 17:13:53 +00:00
if (_recentFld.AutoLoad && !_recentFld.Empty)
{
if (File.Exists(_recent.MostRecent))
{
try
{
2019-12-22 17:13:53 +00:00
_autoloading = true;
LoadFile(_recent.MostRecent);
}
finally
{
2019-12-22 17:13:53 +00:00
_autoloading = false;
}
SetCurrentFilename(_recent.MostRecent);
}
}
2017-04-15 19:53:02 +00:00
}
private void CDL_DragEnter(object sender, DragEventArgs e)
2017-04-15 19:53:02 +00:00
{
e.Set(DragDropEffects.Copy);
2017-04-15 19:53:02 +00:00
}
private void CDL_DragDrop(object sender, DragEventArgs e)
2017-04-15 19:53:02 +00:00
{
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
if (Path.GetExtension(filePaths[0]) == ".cdl")
{
LoadFile(filePaths[0]);
}
}
private void tsbViewStyle_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateDisplay(true);
}
private void tsbLoggingActive_CheckedChanged(object sender, EventArgs e)
{
if (tsbLoggingActive.Checked && _cdl == null)
{
//implicitly create a new file
NewFileLogic();
}
if (_cdl != null && tsbLoggingActive.Checked)
CodeDataLogger.SetCDL(_cdl);
else
CodeDataLogger.SetCDL(null);
}
private void lvCDL_QueryItemText(int index, RollColumn column, out string text, ref int offsetX, ref int offsetY)
2017-04-15 19:53:02 +00:00
{
2019-10-19 20:21:45 +00:00
var subItem = lvCDL.AllColumns.IndexOf(column);
2019-12-22 17:13:53 +00:00
text = _listContents[index][subItem];
2017-04-15 19:53:02 +00:00
}
private void tsbExportText_Click(object sender, EventArgs e)
{
2019-11-02 04:29:09 +00:00
using var sw = new StringWriter();
2019-12-22 17:13:53 +00:00
foreach(var line in _listContents)
2017-04-15 19:53:02 +00:00
{
foreach (var entry in line)
sw.Write("{0} |", entry);
sw.WriteLine();
}
Clipboard.SetText(sw.ToString());
}
private void miAutoSave_Click(object sender, EventArgs e)
{
CDLAutoSave ^= true;
}
private void miAutoStart_Click(object sender, EventArgs e)
{
CDLAutoStart ^= true;
}
private void miAutoResume_Click(object sender, EventArgs e)
{
CDLAutoResume ^= true;
}
2017-04-15 19:53:02 +00:00
}
}