1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-11 17:29:29 +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:
Andy McFadden 2019-11-25 14:27:38 -08:00
parent bef664ae7e
commit 836626bdc3
14 changed files with 747 additions and 32 deletions

View File

@ -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().

View File

@ -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.

View File

@ -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.

View File

@ -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;
}

View File

@ -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) {

View 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();
}
}
}

View File

@ -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");
}
}

View File

@ -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
View 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;
}
}
}

View File

@ -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;
}
}
}

View 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>

View 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);
}
}
}

View File

@ -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"

View File

@ -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) {
}
}
}