Begin work on GUI with Gtk#.

This commit is contained in:
Starbeamrainbowlabs 2016-08-01 19:54:47 +01:00
parent 57ebb57335
commit c4ecc51245
8 changed files with 353 additions and 0 deletions

View file

@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using Gtk;
namespace SilentorBit
{
/// <summary>
/// <para>A single column list, text comes from object.ToString()</para>
/// <para>For multicolumns, see ListView&lt;ClassType&gt;</para>
/// <para>By SilentorBit from https://silentorbit.com/notes/2011/05/gtk-sharp-listview/</para>
/// </summary>
public class ListView : ListView<object>
{
public ListView (string columnTitle) : base(columnTitle)
{
}
protected override void RenderCell (CellRendererText render, int index, object item)
{
render.Text = item.ToString ();
}
}
/// <summary>
/// The list only contains one type of object.
/// To get multiple columns, pass that number of parameters to the constructor
/// and implement RenderCell accordingly.
/// </summary>
public abstract class ListView<T> : TreeView
{
/// <summary>
/// List of all items selected
/// </summary>
public T[] SelectedItems { get; private set; }
public event Action<T[]> ItemSelected;
public event Action<T> ItemActivated;
protected abstract void RenderCell (CellRendererText render, int index, T item);
ListStore store = new ListStore (typeof(T));
Dictionary<T, TreeIter> storeList = new Dictionary<T, TreeIter> ();
List<TreeViewColumn> columns = new List<TreeViewColumn> ();
/// <summary>
/// Pass one string parameter for every column
/// </summary>
/// <param name="columnNames">
/// Column Titles, one parameter for each column.
/// </param>
public ListView (params string[] columnNames)
{
this.Model = store;
foreach (string s in columnNames) {
TreeViewColumn c = this.AppendColumn (s, new CellRendererText (), this.ColumnCellData);
columns.Add (c);
}
this.SelectedItems = new T[0];
this.Selection.Changed += HandleSelectionChanged;
}
private void ColumnCellData (TreeViewColumn column, CellRenderer renderer, ITreeModel model, TreeIter iter)
{
T item = (T)model.GetValue (iter, 0);
CellRendererText textRender = (CellRendererText)renderer;
int index = columns.IndexOf (column);
RenderCell (textRender, index, item);
}
#region Add, Remove and Clear Items
public void AddItem (T item)
{
var iter = store.AppendValues (item);
storeList.Add (item, iter);
}
public void ClearItems ()
{
store.Clear ();
storeList.Clear ();
}
public void RemoveItem (T item)
{
if (! storeList.ContainsKey (item))
return;
TreeIter iter = storeList[item];
store.Remove (ref iter);
storeList.Remove (item);
}
#endregion
#region Selection and Aktivation triggers
void HandleSelectionChanged (object sender, EventArgs e)
{
TreeSelection selection = (TreeSelection)sender;
TreePath[] paths = selection.GetSelectedRows ();
T[] items = new T[paths.Length];
for (int n = 0; n < paths.Length; n++) {
TreeIter iter;
Model.GetIter (out iter, paths[n]);
items[n] = (T)Model.GetValue (iter, 0);
}
SelectedItems = items;
var itemEvent = ItemSelected;
if (itemEvent != null)
itemEvent (items);
}
protected override void OnRowActivated (TreePath path, TreeViewColumn column)
{
TreeIter iter;
Model.GetIter (out iter, path);
T item = (T)Model.GetValue (iter, 0);
var e = ItemActivated;
if (e != null)
e (item);
base.OnRowActivated (path, column);
}
#endregion
}
}

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Gtk;
using SilentorBit;
namespace SpritePacker.GUI
{
public class MainWindow : Window
{
private static bool initialised = false;
private SpriteListView spriteListDisplay;
public MainWindow() : base("SpritePacker GUI")
{
if (!initialised)
throw new InvalidOperationException("Error: Gtk hasn't been initialised yet, so you can't create a new window.");
SetDefaultSize(500, 300);
SetPosition(WindowPosition.Center);
// Quit when the close button is pressed
DeleteEvent += (object o, DeleteEventArgs args) => {
Application.Quit();
};
setupLayout();
}
/// <summary>
/// Initilise GTK# to make it ready for use.
/// </summary>
public static void Init()
{
initialised = true;
Application.Init();
}
public void Start()
{
ShowAll();
Application.Run();
}
private void setupLayout()
{
HBox masterContainer = new HBox(true, 10);
VBox leftPanel = new VBox(false, 0) { MarginRight = 5 };
VBox rightPanel = new VBox(false, 0) { MarginLeft = 5 };
Frame leftPanelFrame = new Frame("Sprites") { Child = leftPanel, Margin = 10, MarginRight = 5 };
Frame rightPanelFrame = new Frame("Preview") { Child = rightPanel, Margin = 10, MarginLeft = 5 };
spriteListDisplay = new SpriteListView() { Margin = 10 };
spriteListDisplay.AddItem(new Sprite("/home/sbrl/Pictures/Spaghetti.png"));
leftPanel.OverrideBackgroundColor(StateFlags.Normal, Gdk.RGBA.Zero);
leftPanel.PackStart(spriteListDisplay, true, true, 0);
masterContainer.PackStart(leftPanelFrame, true, true, 0);
masterContainer.PackStart(rightPanelFrame, true, true, 0);
Add(masterContainer);
}
}
}

View file

@ -0,0 +1,14 @@
using System;
namespace SpritePacker.GUI
{
class MainClass
{
public static void Main(string[] args)
{
MainWindow.Init();
MainWindow mainWindow = new MainWindow();
mainWindow.Start();
}
}
}

View file

@ -0,0 +1,27 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("SpritePacker-GUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Starbeamrainbowlabs")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View file

@ -0,0 +1,29 @@
using System;
using SilentorBit;
using System.IO;
namespace SpritePacker.GUI
{
public class SpriteListView : ListView<Sprite>
{
public SpriteListView() : base("Number", "Filepath")
{
}
protected override void RenderCell(Gtk.CellRendererText render, int index, Sprite item)
{
switch(index)
{
case 0:
render.Text = index.ToString();
break;
case 1:
render.Text = item.Filename;
break;
default:
throw new InvalidDataException($"Invalid column index {index}");
}
}
}
}

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{ECC09EBE-FE69-4DC2-B553-B92DF4992762}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>SpritePacker.GUI</RootNamespace>
<AssemblyName>SpritePacker-GUI</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="atk-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\atk-sharp.dll</HintPath>
</Reference>
<Reference Include="cairo-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\cairo-sharp.dll</HintPath>
</Reference>
<Reference Include="gdk-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\gdk-sharp.dll</HintPath>
</Reference>
<Reference Include="gio-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\gio-sharp.dll</HintPath>
</Reference>
<Reference Include="glib-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\glib-sharp.dll</HintPath>
</Reference>
<Reference Include="gtk-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\gtk-sharp.dll</HintPath>
</Reference>
<Reference Include="pango-sharp">
<HintPath>..\packages\GtkSharp.3.1.3\lib\net45\pango-sharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MainWindow.cs" />
<Compile Include="ListView.cs" />
<Compile Include="SpriteListView.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\GtkSharp.3.1.3\build\net45\GtkSharp.targets" Condition="Exists('..\packages\GtkSharp.3.1.3\build\net45\GtkSharp.targets')" />
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SpritePacker\SpritePacker.csproj">
<Project>{2D3C4FAA-6D9C-4644-ABC0-361550A1884A}</Project>
<Name>SpritePacker</Name>
</ProjectReference>
</ItemGroup>
</Project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="GtkSharp" version="3.1.3" targetFramework="net45" />
</packages>

View file

@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpritePacker", "SpritePacker\SpritePacker.csproj", "{2D3C4FAA-6D9C-4644-ABC0-361550A1884A}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpritePacker", "SpritePacker\SpritePacker.csproj", "{2D3C4FAA-6D9C-4644-ABC0-361550A1884A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpritePacker-GUI", "SpritePacker-GUI\SpritePacker-GUI.csproj", "{ECC09EBE-FE69-4DC2-B553-B92DF4992762}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
@ -25,6 +27,10 @@ Global
{6EF47B64-1920-4827-BEEF-B262D5A2D214}.Debug|x86.Build.0 = Debug|x86 {6EF47B64-1920-4827-BEEF-B262D5A2D214}.Debug|x86.Build.0 = Debug|x86
{6EF47B64-1920-4827-BEEF-B262D5A2D214}.Release|x86.ActiveCfg = Release|x86 {6EF47B64-1920-4827-BEEF-B262D5A2D214}.Release|x86.ActiveCfg = Release|x86
{6EF47B64-1920-4827-BEEF-B262D5A2D214}.Release|x86.Build.0 = Release|x86 {6EF47B64-1920-4827-BEEF-B262D5A2D214}.Release|x86.Build.0 = Release|x86
{ECC09EBE-FE69-4DC2-B553-B92DF4992762}.Debug|x86.ActiveCfg = Debug|x86
{ECC09EBE-FE69-4DC2-B553-B92DF4992762}.Debug|x86.Build.0 = Debug|x86
{ECC09EBE-FE69-4DC2-B553-B92DF4992762}.Release|x86.ActiveCfg = Release|x86
{ECC09EBE-FE69-4DC2-B553-B92DF4992762}.Release|x86.Build.0 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
EndGlobalSection EndGlobalSection