mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-29 08:29:52 +00:00
Work in progress on visualization
Basic infrastructure for taking a list of parameters from a plugin and turning it into a collection of UI controls, merging in values from a Visualization object. Doesn't yet do anything useful. WPF makes the hard things easy and the easy things hard. This was a hard thing, so it was easy to do (with some helpful sample code). Yay WPF?
This commit is contained in:
parent
bef664ae7e
commit
836626bdc3
@ -123,6 +123,55 @@ namespace PluginCommon {
|
||||
void CheckBrk(int offset, bool isTwoBytes, out bool noContinue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension scripts that want to generate 2D visualizations must implement this interface.
|
||||
/// </summary>
|
||||
public interface IPlugin_Visualizer2d {
|
||||
string[] GetVisGenNames();
|
||||
|
||||
List<VisParamDescr> GetVisGenParams(string name);
|
||||
|
||||
IVisualization2d ExecuteVisGen(string name, Dictionary<string, object> parms);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visualization parameter descriptor.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class VisParamDescr {
|
||||
public enum SpecialMode {
|
||||
None = 0, Offset
|
||||
}
|
||||
|
||||
public string UiLabel { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public Type CsType { get; private set; }
|
||||
public object Min { get; private set; }
|
||||
public object Max { get; private set; }
|
||||
public SpecialMode Special { get; private set; }
|
||||
public object DefaultValue { get; private set; }
|
||||
|
||||
public VisParamDescr(string uiLabel, string name, Type csType, object min, object max,
|
||||
SpecialMode special, object defVal) {
|
||||
UiLabel = uiLabel;
|
||||
Name = name;
|
||||
CsType = csType;
|
||||
Min = min;
|
||||
Max = max;
|
||||
Special = special;
|
||||
DefaultValue = defVal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rendered 2D visualization object.
|
||||
/// </summary>
|
||||
public interface IVisualization2d {
|
||||
int GetWidth();
|
||||
int GetHeight();
|
||||
int GetPixel(int x, int y); // returns ARGB value
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interfaces provided by the application for use by plugins. An IApplication instance
|
||||
/// is passed to the plugin as an argument Prepare().
|
||||
|
@ -2443,6 +2443,11 @@ namespace SourceGen {
|
||||
return bestSym;
|
||||
}
|
||||
|
||||
public PluginCommon.IPlugin GetMatchingScript(ScriptManager.CheckMatch check) {
|
||||
return mScriptManager.GetMatchingScript(check);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// For debugging purposes, get some information about the currently loaded
|
||||
/// extension scripts.
|
||||
|
@ -510,7 +510,7 @@ namespace SourceGen {
|
||||
mProject.VisualizationSets.TryGetValue(line.FileOffset,
|
||||
out VisualizationSet visSet);
|
||||
parts = FormattedParts.CreateLongComment("!VISUALIZATION SET! " +
|
||||
(visSet != null ? visSet.PlaceHolder : "???"));
|
||||
(visSet != null ? "VS:" + visSet.Count : "???"));
|
||||
break;
|
||||
case Line.Type.Blank:
|
||||
// Nothing to do.
|
||||
|
@ -2160,8 +2160,8 @@ namespace SourceGen {
|
||||
int offset = CodeLineList[selIndex].FileOffset;
|
||||
mProject.VisualizationSets.TryGetValue(offset, out VisualizationSet curVisSet);
|
||||
|
||||
EditVisualizationSet dlg = new EditVisualizationSet(mMainWin,
|
||||
curVisSet);
|
||||
EditVisualizationSet dlg = new EditVisualizationSet(mMainWin, mProject,
|
||||
mOutputFormatter, curVisSet);
|
||||
if (dlg.ShowDialog() != true) {
|
||||
return;
|
||||
}
|
||||
|
@ -156,9 +156,7 @@ namespace RuntimeData.Apple {
|
||||
private AddressTranslate mAddrTrans;
|
||||
|
||||
public string Identifier {
|
||||
get {
|
||||
return "Apple II ProDOS 8 MLI call handler";
|
||||
}
|
||||
get { return "Apple II ProDOS 8 MLI call handler"; }
|
||||
}
|
||||
|
||||
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
|
||||
|
76
SourceGen/RuntimeData/Apple/VisHiRes.cs
Normal file
76
SourceGen/RuntimeData/Apple/VisHiRes.cs
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2018 faddenSoft
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using PluginCommon;
|
||||
|
||||
namespace RuntimeData.Apple {
|
||||
public class VisHiRes : MarshalByRefObject, IPlugin, IPlugin_Visualizer2d {
|
||||
// Visualization identifiers; DO NOT change.
|
||||
private const string VIS_GEN_BITMAP = "apple2-hi-res-bitmap";
|
||||
|
||||
public string Identifier {
|
||||
get { return "Apple II Hi-Res Graphic Visualizer"; }
|
||||
}
|
||||
|
||||
private IApplication mAppRef;
|
||||
private byte[] mFileData;
|
||||
private AddressTranslate mAddrTrans;
|
||||
|
||||
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
|
||||
mAppRef = appRef;
|
||||
mFileData = fileData;
|
||||
mAddrTrans = addrTrans;
|
||||
}
|
||||
|
||||
public string[] GetVisGenNames() {
|
||||
return new string[] {
|
||||
VIS_GEN_BITMAP,
|
||||
};
|
||||
}
|
||||
|
||||
public List<VisParamDescr> GetVisGenParams(string name) {
|
||||
List<VisParamDescr> parms = new List<VisParamDescr>();
|
||||
|
||||
switch (name) {
|
||||
case VIS_GEN_BITMAP:
|
||||
parms.Add(new VisParamDescr("File Offset",
|
||||
"offset", typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset,
|
||||
0x2000));
|
||||
parms.Add(new VisParamDescr("Width (bytes)",
|
||||
"byteWidth", typeof(int), 1, 40, 0, 1));
|
||||
parms.Add(new VisParamDescr("Height",
|
||||
"height", typeof(int), 1, 192, 0, 1));
|
||||
parms.Add(new VisParamDescr("Color",
|
||||
"color", typeof(bool), 0, 0, 0, true));
|
||||
parms.Add(new VisParamDescr("Test Float",
|
||||
"floaty", typeof(float), -5.0f, 5.0f, 0, 0.1f));
|
||||
break;
|
||||
default:
|
||||
parms = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return parms;
|
||||
}
|
||||
|
||||
public IVisualization2d ExecuteVisGen(string name, Dictionary<string, object> parms) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -256,6 +256,25 @@ namespace SourceGen.Sandbox {
|
||||
return plSymbols;
|
||||
}
|
||||
|
||||
public delegate bool CheckMatch(IPlugin plugin);
|
||||
public IPlugin GetMatchingScript(CheckMatch check) {
|
||||
if (DomainMgr == null) {
|
||||
foreach (KeyValuePair<string, IPlugin> kvp in mActivePlugins) {
|
||||
if (check(kvp.Value)) {
|
||||
return kvp.Value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<IPlugin> plugins = DomainMgr.PluginMgr.GetActivePlugins();
|
||||
foreach (IPlugin plugin in plugins) {
|
||||
if (check(plugin)) {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For debugging purposes, get some information about the currently loaded
|
||||
/// extension scripts.
|
||||
@ -289,7 +308,7 @@ namespace SourceGen.Sandbox {
|
||||
|
||||
// The plugin is actually a MarshalByRefObject, so we can't use reflection
|
||||
// to gather the list of interfaces.
|
||||
// TODO(maybe): add a call that does the query on the remote site
|
||||
// TODO(maybe): add a call that does a reflection query on the remote side
|
||||
if (plugin is PluginCommon.IPlugin_SymbolList) {
|
||||
sb.Append(" SymbolList");
|
||||
}
|
||||
@ -302,6 +321,9 @@ namespace SourceGen.Sandbox {
|
||||
if (plugin is PluginCommon.IPlugin_InlineBrk) {
|
||||
sb.Append(" InlineBrk");
|
||||
}
|
||||
if (plugin is PluginCommon.IPlugin_Visualizer2d) {
|
||||
sb.Append(" Visualizer2d");
|
||||
}
|
||||
sb.Append("\r\n");
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +96,7 @@
|
||||
<DependentUpon>ShowText.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LocalVariableTable.cs" />
|
||||
<Compile Include="Visualization.cs" />
|
||||
<Compile Include="VisualizationSet.cs" />
|
||||
<Compile Include="WpfGui\AboutBox.xaml.cs">
|
||||
<DependentUpon>AboutBox.xaml</DependentUpon>
|
||||
@ -133,6 +134,9 @@
|
||||
<Compile Include="WpfGui\EditProjectProperties.xaml.cs">
|
||||
<DependentUpon>EditProjectProperties.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WpfGui\EditVisualization.xaml.cs">
|
||||
<DependentUpon>EditVisualization.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WpfGui\EditVisualizationSet.xaml.cs">
|
||||
<DependentUpon>EditVisualizationSet.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -314,6 +318,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WpfGui\EditVisualization.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WpfGui\EditVisualizationSet.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
108
SourceGen/Visualization.cs
Normal file
108
SourceGen/Visualization.cs
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2019 faddenSoft
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using PluginCommon;
|
||||
|
||||
namespace SourceGen {
|
||||
public class Visualization {
|
||||
/// <summary>
|
||||
/// Unique tag. Contents are arbitrary, but may not be empty.
|
||||
/// </summary>
|
||||
public string Tag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of visualization generator (extension script function).
|
||||
/// </summary>
|
||||
public string VisGenName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameters passed to the visualization generator.
|
||||
/// </summary>
|
||||
public Dictionary<string, object> VisGenParams { get; private set; }
|
||||
|
||||
public double Thumbnail { get; } // TODO - 64x64(?) bitmap
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="tag"></param>
|
||||
/// <param name="visGenName"></param>
|
||||
/// <param name="visGenParams"></param>
|
||||
public Visualization(string tag, string visGenName,
|
||||
Dictionary<string, object> visGenParams) {
|
||||
Tag = tag;
|
||||
VisGenName = visGenName;
|
||||
VisGenParams = visGenParams;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds a plugin that provides the named visualization generator.
|
||||
/// </summary>
|
||||
/// <param name="proj">Project with script manager.</param>
|
||||
/// <param name="visGenName">Visualization generator name.</param>
|
||||
/// <returns>A plugin that matches, or null if none found.</returns>
|
||||
public static IPlugin_Visualizer2d FindPluginByVisGenName(DisasmProject proj,
|
||||
string visGenName) {
|
||||
Sandbox.ScriptManager.CheckMatch check = (chkPlug) => {
|
||||
if (!(chkPlug is IPlugin_Visualizer2d)) {
|
||||
return false;
|
||||
}
|
||||
IPlugin_Visualizer2d vplug = (IPlugin_Visualizer2d)chkPlug;
|
||||
string[] names = vplug.GetVisGenNames();
|
||||
foreach (string name in names) {
|
||||
if (name == visGenName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return (IPlugin_Visualizer2d)proj.GetMatchingScript(check);
|
||||
}
|
||||
|
||||
|
||||
public override string ToString() {
|
||||
return "[Vis: " + Tag + " (" + VisGenName + ")]";
|
||||
}
|
||||
|
||||
public static bool operator ==(Visualization a, Visualization b) {
|
||||
if (ReferenceEquals(a, b)) {
|
||||
return true; // same object, or both null
|
||||
}
|
||||
if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) {
|
||||
return false; // one is null
|
||||
}
|
||||
// All fields must be equal.
|
||||
if (a.Tag != b.Tag || a.VisGenName != b.VisGenName || a.Thumbnail != b.Thumbnail) {
|
||||
return false;
|
||||
}
|
||||
return a.VisGenParams != b.VisGenParams; // TODO(xyzzy): should be item-by-item
|
||||
}
|
||||
public static bool operator !=(Visualization a, Visualization b) {
|
||||
return !(a == b);
|
||||
}
|
||||
public override bool Equals(object obj) {
|
||||
return obj is Visualization && this == (Visualization)obj;
|
||||
}
|
||||
public override int GetHashCode() {
|
||||
return Tag.GetHashCode() ^ VisGenName.GetHashCode() ^ VisGenParams.Count;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,23 +14,50 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGen {
|
||||
public class VisualizationSet {
|
||||
// TODO(xyzzy)
|
||||
public string PlaceHolder { get; private set; }
|
||||
public class VisualizationSet : IEnumerable<Visualization> {
|
||||
/// <summary>
|
||||
/// Ordered list of visualization objects.
|
||||
/// </summary>
|
||||
private List<Visualization> mList;
|
||||
|
||||
public VisualizationSet(string placeHolder) {
|
||||
PlaceHolder = placeHolder;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="cap">Initial capacity.</param>
|
||||
public VisualizationSet(int cap = 1) {
|
||||
mList = new List<Visualization>(cap);
|
||||
}
|
||||
|
||||
// IEnumerable
|
||||
public IEnumerator<Visualization> GetEnumerator() {
|
||||
return mList.GetEnumerator();
|
||||
}
|
||||
|
||||
// IEnumerable
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return mList.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of entries in the table.
|
||||
/// </summary>
|
||||
public int Count {
|
||||
get { return mList.Count; }
|
||||
}
|
||||
|
||||
public void Add(Visualization vis) {
|
||||
mList.Add(vis);
|
||||
}
|
||||
|
||||
|
||||
public override string ToString() {
|
||||
return "[VS: " + PlaceHolder + "]";
|
||||
return "[VS: " + mList.Count + " items]";
|
||||
}
|
||||
|
||||
public static bool operator ==(VisualizationSet a, VisualizationSet b) {
|
||||
@ -41,7 +68,16 @@ namespace SourceGen {
|
||||
return false; // one is null
|
||||
}
|
||||
// All fields must be equal.
|
||||
return a.PlaceHolder == b.PlaceHolder;
|
||||
if (a.mList.Count != b.mList.Count) {
|
||||
return false;
|
||||
}
|
||||
// Order matters.
|
||||
for (int i = 0; i < a.mList.Count; i++) {
|
||||
if (a.mList[i] != b.mList[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static bool operator !=(VisualizationSet a, VisualizationSet b) {
|
||||
return !(a == b);
|
||||
@ -50,7 +86,11 @@ namespace SourceGen {
|
||||
return obj is VisualizationSet && this == (VisualizationSet)obj;
|
||||
}
|
||||
public override int GetHashCode() {
|
||||
return PlaceHolder.GetHashCode();
|
||||
int hashCode = 0;
|
||||
foreach (Visualization vis in mList) {
|
||||
hashCode ^= vis.GetHashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
120
SourceGen/WpfGui/EditVisualization.xaml
Normal file
120
SourceGen/WpfGui/EditVisualization.xaml
Normal file
@ -0,0 +1,120 @@
|
||||
<!--
|
||||
Copyright 2019 faddenSoft
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<Window x:Class="SourceGen.WpfGui.EditVisualization"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SourceGen.WpfGui"
|
||||
mc:Ignorable="d"
|
||||
Title="Edit Visualization"
|
||||
Width="460" SizeToContent="Height" ResizeMode="NoResize"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||
Loaded="Window_Loaded">
|
||||
|
||||
<Window.Resources>
|
||||
<!-- big thanks: http://drwpf.com/blog/2008/01/03/itemscontrol-d-is-for-datatemplate/ -->
|
||||
<DataTemplate x:Key="BoolTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Width="100" Text="{Binding UiName}"/>
|
||||
<CheckBox IsChecked="{Binding Value}"/>
|
||||
<TextBlock Text="{Binding RangeText}" FontFamily="{StaticResource GeneralMonoFont}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="IntTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Width="100" Text="{Binding UiName}"/>
|
||||
<TextBox Width="100" MaxLength="11" Text="{Binding Value}"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
<TextBlock Text="{Binding RangeText}" FontFamily="{StaticResource GeneralMonoFont}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="FloatTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Width="100" Text="{Binding UiName}"/>
|
||||
<TextBox Width="100" MaxLength="11" Text="{Binding Value}"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
<TextBlock Text="{Binding RangeText}" FontFamily="{StaticResource GeneralMonoFont}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- define and configure the template selector, which chooses one of the above
|
||||
templates based on the parameter data type -->
|
||||
<local:ParameterTemplateSelector x:Key="ParameterTemplateSelector"
|
||||
BoolTemplate="{StaticResource BoolTemplate}"
|
||||
IntTemplate="{StaticResource IntTemplate}"
|
||||
FloatTemplate="{StaticResource FloatTemplate}"/>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" Margin="0,0,4,0"
|
||||
Text="Visualizer:"/>
|
||||
<ComboBox Grid.Column="1" Grid.Row="0" />
|
||||
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" Margin="0,0,4,0"
|
||||
Text="Tag:"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="1" Width="300"
|
||||
Text="{Binding TagString, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
|
||||
<TextBlock Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Margin="0,20,0,0" Text="Preview:"/>
|
||||
</Grid>
|
||||
|
||||
<Image Grid.Row="1" Width="50" Height="50"/>
|
||||
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Text="Parameters:"/>
|
||||
|
||||
<!-- generated controls are placed here -->
|
||||
<ItemsControl Grid.Row="1"
|
||||
ItemsSource="{Binding ParameterList}"
|
||||
ItemTemplateSelector="{StaticResource ParameterTemplateSelector}">
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
|
||||
<DockPanel Grid.Column="0" Grid.Row="3" Margin="0,8,0,0" LastChildFill="False">
|
||||
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" Margin="8,0,0,0" IsCancel="True"/>
|
||||
<Button DockPanel.Dock="Right" Grid.Column="1" Content="OK" Width="70"
|
||||
IsDefault="True" Click="OkButton_Click"/>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Window>
|
194
SourceGen/WpfGui/EditVisualization.xaml.cs
Normal file
194
SourceGen/WpfGui/EditVisualization.xaml.cs
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 2019 faddenSoft
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
using Asm65;
|
||||
using PluginCommon;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
/// <summary>
|
||||
/// Visualization editor.
|
||||
/// </summary>
|
||||
public partial class EditVisualization : Window, INotifyPropertyChanged {
|
||||
private DisasmProject mProject;
|
||||
private Formatter mFormatter;
|
||||
private Visualization mOrigVis;
|
||||
|
||||
public string TagString {
|
||||
get { return mTagString; }
|
||||
set { mTagString = value; OnPropertyChanged(); }
|
||||
}
|
||||
private string mTagString;
|
||||
|
||||
public IList<ParameterValue> ParameterList {
|
||||
get { return mParameterList; }
|
||||
}
|
||||
private List<ParameterValue> mParameterList;
|
||||
|
||||
// INotifyPropertyChanged implementation
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public EditVisualization(Window owner, DisasmProject proj, Formatter formatter,
|
||||
Visualization vis) {
|
||||
InitializeComponent();
|
||||
Owner = owner;
|
||||
DataContext = this;
|
||||
|
||||
mProject = proj;
|
||||
mFormatter = formatter;
|
||||
mOrigVis = vis;
|
||||
|
||||
// TODO: configure ComboBox from vis arg if non-null, then use current
|
||||
// combo box selection, updating in selchange event
|
||||
string visGenName = "apple2-hi-res-bitmap";
|
||||
|
||||
mParameterList = new List<ParameterValue>();
|
||||
GenerateParamControls(visGenName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the list of parameter controls.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We need to get the list of parameters from the VisGen plugin, then for each
|
||||
/// parameter we need to merge the value from the Visualization's value list.
|
||||
/// If we don't find a corresponding entry in the Visualization, we use the
|
||||
/// default value.
|
||||
/// </remarks>
|
||||
private void GenerateParamControls(string visGenName) {
|
||||
IPlugin_Visualizer2d plugin =
|
||||
Visualization.FindPluginByVisGenName(mProject, visGenName);
|
||||
List<VisParamDescr> descrs = plugin.GetVisGenParams(visGenName);
|
||||
|
||||
mParameterList.Clear();
|
||||
foreach (VisParamDescr vpd in descrs) {
|
||||
string rangeStr = string.Empty;
|
||||
object defaultVal = vpd.DefaultValue;
|
||||
if (mOrigVis.VisGenParams.TryGetValue(vpd.Name, out object val)) {
|
||||
// Do we need to confirm that val has the correct type?
|
||||
defaultVal = val;
|
||||
}
|
||||
|
||||
if (vpd.CsType == typeof(int) || vpd.CsType == typeof(float)) {
|
||||
if (vpd.Special == VisParamDescr.SpecialMode.Offset) {
|
||||
defaultVal = mFormatter.FormatOffset24((int)defaultVal);
|
||||
rangeStr = "[" + mFormatter.FormatOffset24(0) + "," +
|
||||
mFormatter.FormatOffset24(mProject.FileDataLength - 1) + "]";
|
||||
} else {
|
||||
rangeStr = "[" + vpd.Min + "," + vpd.Max + "]";
|
||||
}
|
||||
}
|
||||
|
||||
ParameterValue pv = new ParameterValue(vpd.UiLabel, vpd.Name, vpd.CsType,
|
||||
defaultVal, rangeStr);
|
||||
|
||||
mParameterList.Add(pv);
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||
Debug.WriteLine("PARAMS:");
|
||||
foreach (ParameterValue val in mParameterList) {
|
||||
Debug.WriteLine(" " + val.Name + ": " + val.Value +
|
||||
" (" + val.Value.GetType() + ")");
|
||||
}
|
||||
DialogResult = false; // TODO
|
||||
}
|
||||
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e) {
|
||||
TextBox src = (TextBox)sender;
|
||||
ParameterValue pv = (ParameterValue)src.DataContext;
|
||||
Debug.WriteLine("TEXT CHANGE " + pv + ": " + src.Text);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a parameter and holds its value while being edited by WPF.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We use an explicit type so that we can format the initial value as hex or whatever.
|
||||
/// </remarks>
|
||||
public class ParameterValue {
|
||||
public string UiName { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public Type CsType { get; private set; }
|
||||
public object Value { get; set; }
|
||||
public string RangeText { get; private set; }
|
||||
|
||||
public ParameterValue(string uiName, string name, Type csType, object val,
|
||||
string rangeText) {
|
||||
UiName = uiName;
|
||||
Name = name;
|
||||
CsType = csType;
|
||||
Value = val;
|
||||
RangeText = rangeText;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "[PV: " + Name + "=" + Value + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public class ParameterTemplateSelector : DataTemplateSelector {
|
||||
private DataTemplate mBoolTemplate;
|
||||
public DataTemplate BoolTemplate {
|
||||
get { return mBoolTemplate; }
|
||||
set { mBoolTemplate = value; }
|
||||
}
|
||||
private DataTemplate mIntTemplate;
|
||||
public DataTemplate IntTemplate {
|
||||
get { return mIntTemplate; }
|
||||
set { mIntTemplate = value; }
|
||||
}
|
||||
private DataTemplate mFloatTemplate;
|
||||
public DataTemplate FloatTemplate {
|
||||
get { return mFloatTemplate; }
|
||||
set { mFloatTemplate = value; }
|
||||
}
|
||||
|
||||
public override DataTemplate SelectTemplate(object item, DependencyObject container) {
|
||||
if (item is ParameterValue) {
|
||||
ParameterValue parm = (ParameterValue)item;
|
||||
if (parm.CsType == typeof(bool)) {
|
||||
return BoolTemplate;
|
||||
} else if (parm.CsType == typeof(int)) {
|
||||
return IntTemplate;
|
||||
} else if (parm.CsType == typeof(float)) {
|
||||
return FloatTemplate;
|
||||
} else {
|
||||
Debug.WriteLine("WHA?" + parm.Value.GetType());
|
||||
}
|
||||
}
|
||||
return base.SelectTemplate(item, container);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,18 +22,62 @@ limitations under the License.
|
||||
xmlns:local="clr-namespace:SourceGen.WpfGui"
|
||||
mc:Ignorable="d"
|
||||
Title="Edit Visualization Set"
|
||||
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
||||
Width="460" Height="400" ResizeMode="NoResize"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||
Loaded="Window_Loaded">
|
||||
|
||||
<Grid Margin="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBox Grid.Column="0" Grid.Row="0" Text="{Binding PlaceHolder, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<DataGrid Name="visualizationList" Grid.Column="0" Grid.Row="0" Margin="4,4,4,0"
|
||||
ItemsSource="{Binding VisualizationList}"
|
||||
IsReadOnly="True"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"
|
||||
SnapsToDevicePixels="True"
|
||||
GridLinesVisibility="Vertical"
|
||||
VerticalGridLinesBrush="#FF7F7F7F"
|
||||
AutoGenerateColumns="False"
|
||||
HeadersVisibility="Column"
|
||||
CanUserSortColumns="False"
|
||||
CanUserReorderColumns="False"
|
||||
SelectionMode="Single"
|
||||
SelectionChanged="VisualizationList_SelectionChanged"
|
||||
MouseDoubleClick="VisualizationList_MouseDoubleClick">
|
||||
<DataGrid.Resources>
|
||||
<!-- make the no-focus color the same as the in-focus color -->
|
||||
<!-- thanks: https://stackoverflow.com/a/13053511/294248 -->
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
|
||||
Color="{x:Static SystemColors.HighlightColor}"/>
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}"
|
||||
Color="{x:Static SystemColors.HighlightTextColor}"/>
|
||||
</DataGrid.Resources>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Tag" Width="155" Binding="{Binding Tag}"/>
|
||||
<DataGridTextColumn Header="Visualization Generator" Width="180" Binding="{Binding VisGenName}"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.Row="0">
|
||||
<Button Width="75" Margin="4" Content="_New..."
|
||||
Click="NewButton_Click"/>
|
||||
<Button Width="75" Margin="4" Content="_Edit"
|
||||
Click="EditButton_Click"/>
|
||||
<Button Width="75" Margin="4" Content="_Remove"
|
||||
Click="RemoveButton_Click"/>
|
||||
|
||||
<Button Width="75" Margin="4,20,4,4" Content="_Up"
|
||||
Click="UpButton_Click"/>
|
||||
<Button Width="75" Margin="4,4" Content="_Down"
|
||||
Click="DownButton_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
<DockPanel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Margin="0,8,0,0" LastChildFill="False">
|
||||
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" Margin="8,0,0,0" IsCancel="True"/>
|
||||
<Button DockPanel.Dock="Right" Grid.Column="1" Content="OK" Width="70"
|
||||
|
@ -15,12 +15,20 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using Asm65;
|
||||
using PluginCommon;
|
||||
using SourceGen.Sandbox;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
/// <summary>
|
||||
/// Visualization set editor.
|
||||
@ -28,11 +36,11 @@ namespace SourceGen.WpfGui {
|
||||
public partial class EditVisualizationSet : Window, INotifyPropertyChanged {
|
||||
public VisualizationSet NewVisSet { get; private set; }
|
||||
|
||||
public string PlaceHolder {
|
||||
get { return mPlaceHolder; }
|
||||
set { mPlaceHolder = value; OnPropertyChanged(); }
|
||||
}
|
||||
private string mPlaceHolder;
|
||||
private DisasmProject mProject;
|
||||
private Formatter mFormatter;
|
||||
|
||||
public ObservableCollection<Visualization> VisualizationList { get; private set; } =
|
||||
new ObservableCollection<Visualization>();
|
||||
|
||||
// INotifyPropertyChanged implementation
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
@ -40,29 +48,72 @@ namespace SourceGen.WpfGui {
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public EditVisualizationSet(Window owner, VisualizationSet curSet) {
|
||||
public EditVisualizationSet(Window owner, DisasmProject project, Formatter formatter,
|
||||
VisualizationSet curSet) {
|
||||
InitializeComponent();
|
||||
Owner = owner;
|
||||
DataContext = this;
|
||||
|
||||
mProject = project;
|
||||
mFormatter = formatter;
|
||||
|
||||
if (curSet != null) {
|
||||
PlaceHolder = curSet.PlaceHolder;
|
||||
} else {
|
||||
PlaceHolder = "New!";
|
||||
foreach (Visualization vis in curSet) {
|
||||
VisualizationList.Add(vis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||
if (string.IsNullOrEmpty(PlaceHolder)) {
|
||||
if (VisualizationList.Count == 0) {
|
||||
NewVisSet = null;
|
||||
} else {
|
||||
NewVisSet = new VisualizationSet(PlaceHolder);
|
||||
NewVisSet = new VisualizationSet(VisualizationList.Count);
|
||||
foreach (Visualization vis in VisualizationList) {
|
||||
NewVisSet.Add(vis);
|
||||
}
|
||||
}
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
private void VisualizationList_SelectionChanged(object sender,
|
||||
SelectionChangedEventArgs e) {
|
||||
Debug.WriteLine("SEL CHANGE");
|
||||
}
|
||||
|
||||
private void VisualizationList_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
|
||||
Debug.WriteLine("DBL CLICK");
|
||||
}
|
||||
|
||||
private void NewButton_Click(object sender, RoutedEventArgs e) {
|
||||
VisualizationList.Add(new Visualization("VIS #" + VisualizationList.Count,
|
||||
"apple2-hi-res-bitmap", new Dictionary<string, object>()));
|
||||
}
|
||||
|
||||
private void EditButton_Click(object sender, RoutedEventArgs e) {
|
||||
Dictionary<string, object> testDict = new Dictionary<string, object>();
|
||||
testDict.Add("offset", 0x1234);
|
||||
testDict.Add("height", 57);
|
||||
EditVisualization dlg = new EditVisualization(this, mProject, mFormatter,
|
||||
new Visualization("arbitrary tag", "apple2-hi-res-bitmap", testDict));
|
||||
if (dlg.ShowDialog() == true) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveButton_Click(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
private void UpButton_Click(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
private void DownButton_Click(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user