New Add dialog for Mac too

This commit is contained in:
Hylke Bons 2011-10-05 23:23:35 +02:00
parent d2d8be033c
commit dcd717a07b
8 changed files with 280 additions and 187 deletions

1
.gitignore vendored
View file

@ -39,3 +39,4 @@ po/sparkleshare.pot
SparkleShare/Nautilus/sparkleshare-nautilus-extension.py
gnome-doc-utils.make
/sparkleshare-*
data/plugins/*.xml

View file

@ -28,6 +28,12 @@ namespace SparkleShare {
public class SparkleController : SparkleControllerBase {
public override string PluginsPath {
get {
return Path.Combine (NSBundle.MainBundle.ResourcePath, "Plugins");
}
}
// We have to use our own custom made folder watcher, as
// System.IO.FileSystemWatcher fails watching subfolders on Mac
private SparkleMacWatcher watcher;

View file

@ -20,6 +20,8 @@ using System.Drawing;
using System.IO;
using System.Timers;
using System.Collections.Generic;
using Mono.Unix;
using MonoMac.Foundation;
using MonoMac.AppKit;
@ -28,37 +30,38 @@ using MonoMac.WebKit;
namespace SparkleShare {
public class SparkleSetup : SparkleSetupWindow {
public class SparkleSetup : SparkleSetupWindow {
public SparkleSetupController Controller = new SparkleSetupController ();
private NSButton ContinueButton;
private NSButton SyncButton;
private NSButton TryAgainButton;
private NSButton CancelButton;
private NSButton SkipTutorialButton;
private NSButton OpenFolderButton;
private NSButton FinishButton;
private NSButton AddProjectButton;
private NSImage SlideImage;
private NSImageView SlideImageView;
private NSForm UserInfoForm;
private NSProgressIndicator ProgressIndicator;
private NSTextField AddressTextField;
private NSTextField FolderNameTextField;
private NSTextField ServerTypeLabel;
private NSTextField AddressLabel;
private NSTextField FolderNameLabel;
private NSTextField FolderNameHelpLabel;
private NSTextField AddProjectTextField;
private NSButtonCell ButtonCellProto;
private NSMatrix Matrix;
private int ServerType;
private Timer timer;
private NSButton ContinueButton;
private NSButton SyncButton;
private NSButton TryAgainButton;
private NSButton CancelButton;
private NSButton SkipTutorialButton;
private NSButton OpenFolderButton;
private NSButton FinishButton;
private NSButton AddProjectButton;
private NSImage SlideImage;
private NSImageView SlideImageView;
private NSForm UserInfoForm;
private NSProgressIndicator ProgressIndicator;
private NSTextField AddressTextField;
private NSTextField PathTextField;
private NSTextField AddressLabel;
private NSTextField PathLabel;
private NSTextField PathHelpLabel;
private NSTextField AddProjectTextField;
private Timer timer;
private NSTableView TableView;
private NSScrollView ScrollView;
private NSTableColumn IconColumn;
private NSTableColumn DescriptionColumn;
private SparkleDataSource DataSource;
public SparkleSetup () : base ()
{
public SparkleSetup () : base ()
{
Controller.ChangePageEvent += delegate (PageType type) {
InvokeOnMainThread (delegate {
Reset ();
@ -124,122 +127,140 @@ namespace SparkleShare {
case PageType.Add: {
Header = "Where is your project?";
Header = "Where's your project hosted?";
Description = "";
ServerTypeLabel = new NSTextField () {
Alignment = NSTextAlignment.Right,
BackgroundColor = NSColor.WindowBackground,
Bordered = false,
Editable = false,
Frame = new RectangleF (150, Frame.Height - 159 , 160, 17),
StringValue = "Host Type:",
Font = SparkleUI.Font
};
AddressLabel = new NSTextField () {
Alignment = NSTextAlignment.Right,
Alignment = NSTextAlignment.Left,
BackgroundColor = NSColor.WindowBackground,
Bordered = false,
Editable = false,
Frame = new RectangleF (150, Frame.Height - 257 , 160, 17),
Frame = new RectangleF (190, Frame.Height - 308, 160, 17),
StringValue = "Address:",
Font = SparkleUI.Font
};
FolderNameLabel = new NSTextField () {
Alignment = NSTextAlignment.Right,
AddressTextField = new NSTextField () {
Frame = new RectangleF (190, Frame.Height - 336, 196, 22),
Font = SparkleUI.Font,
StringValue = Controller.PreviousAddress,
Enabled = (Controller.SelectedPlugin.Address == null)
};
PathLabel = new NSTextField () {
Alignment = NSTextAlignment.Left,
BackgroundColor = NSColor.WindowBackground,
Bordered = false,
Editable = false,
Frame = new RectangleF (150, Frame.Height - 284 , 160, 17),
StringValue = "Folder Name:",
Font = SparkleUI.Font
Frame = new RectangleF (190 + 196 + 16, Frame.Height - 308, 160, 17),
StringValue = "Remote Path:",
Font = SparkleUI.Font,
Enabled = (Controller.SelectedPlugin.Path == null)
};
PathTextField = new NSTextField () {
Frame = new RectangleF (190 + 196 + 16, Frame.Height - 336, 196, 22),
StringValue = Controller.PreviousPath
};
AddressTextField = new NSTextField () {
Frame = new RectangleF (320, Frame.Height - 260 , 256, 22),
Font = SparkleUI.Font,
StringValue = Controller.PreviousServer
};
AddressTextField.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;
PathTextField.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;
AddressTextField.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;
FolderNameTextField = new NSTextField () {
Frame = new RectangleF (320, Frame.Height - (260 + 22 + 4) , 256, 22),
StringValue = Controller.PreviousFolder
};
FolderNameTextField.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;
FolderNameHelpLabel = new NSTextField () {
PathHelpLabel = new NSTextField () {
BackgroundColor = NSColor.WindowBackground,
Bordered = false,
TextColor = NSColor.DisabledControlText,
Editable = false,
Frame = new RectangleF (320, Frame.Height - 305 , 200, 17),
StringValue = "e.g. rupert/website-design"
Frame = new RectangleF (190 + 196 + 16, Frame.Height - 355, 204, 17),
StringValue = "e.g. rupert/website-design",
Font = NSFontManager.SharedFontManager.FontWithFamily
("Lucida Grande", NSFontTraitMask.Condensed, 0, 11)
};
ServerType = 0;
ButtonCellProto = new NSButtonCell ();
ButtonCellProto.SetButtonType (NSButtonType.Radio) ;
TableView = new NSTableView () {
Frame = new RectangleF (0, 0, 0, 0),
RowHeight = 30,
IntercellSpacing = new SizeF (0, 12),
HeaderView = null
};
Matrix = new NSMatrix (new RectangleF (315, Frame.Height - 220, 256, 78),
NSMatrixMode.Radio, ButtonCellProto, 4, 1);
ScrollView = new NSScrollView () {
Frame = new RectangleF (190, Frame.Height - 280, 408, 175),
DocumentView = TableView,
HasVerticalScroller = true,
BorderType = NSBorderType.BezelBorder
};
Matrix.CellSize = new SizeF (256, 18);
IconColumn = new NSTableColumn (new NSImage ()) {
Width = 42,
HeaderToolTip = "Icon",
DataCell = new NSImageCell ()
};
Matrix.Cells [0].Title = "My own server";
Matrix.Cells [1].Title = "Github";
Matrix.Cells [2].Title = "Gitorious";
Matrix.Cells [3].Title = "The GNOME Project";
DescriptionColumn = new NSTableColumn () {
Width = 350,
HeaderToolTip = "Description",
Editable = false
};
DescriptionColumn.DataCell.Font =
NSFontManager.SharedFontManager.FontWithFamily (
"Lucida Grande", NSFontTraitMask.Condensed, 0, 11);
TableView.AddColumn (IconColumn);
TableView.AddColumn (DescriptionColumn);
DataSource = new SparkleDataSource ();
foreach (SparklePlugin plugin in Controller.Plugins)
DataSource.Items.Add (plugin);
TableView.DataSource = DataSource;
TableView.ReloadData ();
Controller.ChangeAddressFieldEvent += delegate (string text,
string example_text, FieldState state) {
InvokeOnMainThread (delegate {
AddressTextField.StringValue = text;
AddressTextField.Enabled = (state == FieldState.Enabled);
});
};
Controller.ChangePathFieldEvent += delegate (string text,
string example_text, FieldState state) {
InvokeOnMainThread (delegate {
PathTextField.StringValue = text;
PathTextField.Enabled = (state == FieldState.Enabled);
if (!string.IsNullOrEmpty (example_text))
PathHelpLabel.StringValue = "e.g. " + example_text;
});
};
TableView.SelectRow (Controller.SelectedPluginIndex, false);
foreach (NSCell cell in Matrix.Cells)
cell.Font = SparkleUI.Font;
// TODO: Ugly hack, do properly with events
timer = new Timer () {
Interval = 50
};
// TODO: Use an event
timer.Elapsed += delegate {
if (TableView.SelectedRow != Controller.SelectedPluginIndex)
Controller.SelectedPluginChanged (TableView.SelectedRow);
InvokeOnMainThread (delegate {
if (Matrix.SelectedRow != ServerType) {
ServerType = Matrix.SelectedRow;
AddressTextField.Enabled = (ServerType == 0);
switch (ServerType) {
case 0:
AddressTextField.StringValue = "";
FolderNameHelpLabel.StringValue = "e.g. rupert/website-design";
break;
case 1:
AddressTextField.StringValue = "ssh://git@github.com/";
FolderNameHelpLabel.StringValue = "e.g. rupert/website-design";
break;
case 2:
AddressTextField.StringValue = "ssh://git@gitorious.org/";
FolderNameHelpLabel.StringValue = "e.g. project/website-design";
break;
case 3:
AddressTextField.StringValue = "ssh://git@gnome.org/git/";
FolderNameHelpLabel.StringValue = "e.g. gnome-icon-theme";
break;
}
}
if (ServerType == 0 && !AddressTextField.StringValue.Trim ().Equals ("")
&& !FolderNameTextField.StringValue.Trim ().Equals ("")) {
SyncButton.Enabled = true;
} else if (ServerType != 0 &&
!FolderNameTextField.StringValue.Trim ().Equals ("")) {
// TODO: Move checking logic to controller
if (!string.IsNullOrWhiteSpace (AddressTextField.StringValue) &&
!string.IsNullOrWhiteSpace (PathTextField.StringValue)) {
SyncButton.Enabled = true;
@ -247,20 +268,17 @@ namespace SparkleShare {
SyncButton.Enabled = false;
}
});
};
timer.Start ();
ContentView.AddSubview (ServerTypeLabel);
ContentView.AddSubview (Matrix);
ContentView.AddSubview (ScrollView);
ContentView.AddSubview (AddressLabel);
ContentView.AddSubview (AddressTextField);
ContentView.AddSubview (FolderNameLabel);
ContentView.AddSubview (FolderNameTextField);
ContentView.AddSubview (FolderNameHelpLabel);
ContentView.AddSubview (PathLabel);
ContentView.AddSubview (PathTextField);
ContentView.AddSubview (PathHelpLabel);
SyncButton = new NSButton () {
Title = "Add",
@ -271,9 +289,10 @@ namespace SparkleShare {
timer.Stop ();
timer = null;
string folder_name = FolderNameTextField.StringValue;
string server = AddressTextField.StringValue;
Controller.AddPageCompleted (server, folder_name);
Controller.AddPageCompleted (
AddressTextField.StringValue,
PathTextField.StringValue
);
};
Buttons.Add (SyncButton);
@ -288,7 +307,7 @@ namespace SparkleShare {
});
};
Buttons.Add (CancelButton);
Buttons.Add (CancelButton);
break;
}
@ -307,7 +326,7 @@ namespace SparkleShare {
Indeterminate = false,
DoubleValue = 1.0
};
ProgressIndicator.StartAnimation (this);
Controller.UpdateProgressBarEvent += delegate (double percentage) {
@ -315,7 +334,7 @@ namespace SparkleShare {
ProgressIndicator.DoubleValue = percentage;
});
};
ContentView.AddSubview (ProgressIndicator);
FinishButton = new NSButton () {
@ -559,5 +578,47 @@ namespace SparkleShare {
});
};
}
}
[Register("SparkleDataSource")]
public class SparkleDataSource : NSTableViewDataSource {
public List<object> Items ;
public SparkleDataSource ()
{
Items = new List<object> ();
}
[Export("numberOfRowsInTableView:")]
public int numberOfRowsInTableView (NSTableView table_view)
{
if (Items == null)
return 0;
else
return Items.Count;
}
[Export("tableView:objectValueForTableColumn:row:")]
public NSObject objectValueForTableColumn (NSTableView table_view,
NSTableColumn table_column, int row_index)
{
// TODO: Style text nicely: "<b>Name</b>\n<grey>Description</grey>"
if (table_column.HeaderToolTip.Equals ("Description")) {
return new NSString (
(Items [row_index] as SparklePlugin).Name + "\n" +
(Items [row_index] as SparklePlugin).Description
);
} else {
return new NSImage ((Items [row_index] as SparklePlugin).ImagePath) {
Size = new SizeF (24, 24)
};
}
}
}
}

View file

@ -109,6 +109,9 @@
<Link>SparkleExtensions.cs</Link>
</Compile>
<Compile Include="SparkleController.cs" />
<Compile Include="..\SparklePlugin.cs">
<Link>SparklePlugin.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Page Include="MainMenu.xib" />
@ -282,10 +285,41 @@
<Content Include="..\..\data\tutorial-slide-4.png">
<Link>Pixmaps\tutorial-slide-4.png</Link>
</Content>
<Content Include="..\..\data\plugins\bitbucket.xml">
<Link>Plugins\bitbucket.xml</Link>
</Content>
<Content Include="..\..\data\plugins\github.xml">
<Link>Plugins\github.xml</Link>
</Content>
<Content Include="..\..\data\plugins\gitorious.xml">
<Link>Plugins\gitorious.xml</Link>
</Content>
<Content Include="..\..\data\plugins\gnome.xml">
<Link>Plugins\gnome.xml</Link>
</Content>
<Content Include="..\..\data\plugins\own-server.xml">
<Link>Plugins\own-server.xml</Link>
</Content>
<Content Include="..\..\data\plugins\bitbucket.png">
<Link>Plugins\bitbucket.png</Link>
</Content>
<Content Include="..\..\data\plugins\github.png">
<Link>Plugins\github.png</Link>
</Content>
<Content Include="..\..\data\plugins\gitorious.png">
<Link>Plugins\gitorious.png</Link>
</Content>
<Content Include="..\..\data\plugins\gnome.png">
<Link>Plugins\gnome.png</Link>
</Content>
<Content Include="..\..\data\plugins\own-server.png">
<Link>Plugins\own-server.png</Link>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Pixmaps\" />
<Folder Include="HTML\" />
<Folder Include="Translations\" />
<Folder Include="Plugins\" />
</ItemGroup>
</Project>

View file

@ -30,6 +30,14 @@ namespace SparkleShare {
public class SparkleController : SparkleControllerBase {
public override string PluginsPath {
get {
return SparkleHelpers.CombineMore (Defines.DATAROOTDIR, "sparkleshare", "plugins");
}
}
public SparkleController () : base ()
{
}

View file

@ -78,6 +78,8 @@ namespace SparkleShare {
public delegate void NotificationRaisedEventHandler (string user_name, string user_email,
string message, string repository_path);
public abstract string PluginsPath { get; }
private SparkleFetcherBase fetcher;

View file

@ -49,13 +49,16 @@ namespace SparkleShare {
public delegate void ChangePathFieldEventHandler (string text,
string example_text, FieldState state);
public event SelectListPluginEventHandler SelectListPluginEvent;
public delegate void SelectListPluginEventHandler (int index);
public readonly List<SparklePlugin> Plugins = new List<SparklePlugin> ();
public SparklePlugin SelectedPlugin;
public int SelectedPluginIndex {
get {
return Plugins.IndexOf (SelectedPlugin);
}
}
public int TutorialPageNumber {
get {
return this.tutorial_page_number;
@ -68,15 +71,15 @@ namespace SparkleShare {
}
}
public string PreviousServer {
public string PreviousAddress {
get {
return this.previous_server;
return this.previous_address;
}
}
public string PreviousFolder {
public string PreviousPath {
get {
return this.previous_folder;
return this.previous_path;
}
}
@ -108,8 +111,8 @@ namespace SparkleShare {
}
private string previous_server = "";
private string previous_folder = "";
private string previous_address = "";
private string previous_path = "";
private string previous_url = "";
private string syncing_folder = "";
private int tutorial_page_number = 1;
@ -122,15 +125,12 @@ namespace SparkleShare {
Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
"sparkleshare", "plugins");
string plugins_path = SparkleHelpers.CombineMore (
Defines.DATAROOTDIR, "sparkleshare", "plugins");
if (Directory.Exists (local_plugins_path))
foreach (string xml_file_path in Directory.GetFiles (local_plugins_path, "*.xml"))
Plugins.Add (new SparklePlugin (xml_file_path));
if (Directory.Exists (plugins_path)) {
foreach (string xml_file_path in Directory.GetFiles (plugins_path, "*.xml")) {
if (Directory.Exists (Program.Controller.PluginsPath)) {
foreach (string xml_file_path in Directory.GetFiles (Program.Controller.PluginsPath, "*.xml")) {
if (xml_file_path.EndsWith ("own-server.xml"))
Plugins.Insert (0, new SparklePlugin (xml_file_path));
else
@ -138,31 +138,14 @@ namespace SparkleShare {
}
}
SelectedPlugin = Plugins [0];
ChangePageEvent += delegate (PageType page) {
this.previous_page = page;
};
}
public void ShowAddPage ()
{
if (ChangePageEvent != null)
ChangePageEvent (PageType.Add);
int index;
if (SelectedPlugin == null)
index = 0;
else
index = Plugins.IndexOf (SelectedPlugin);
if (SelectListPluginEvent != null)
SelectListPluginEvent (index);
SelectedPluginChanged (index);
SelectedPlugin = null;
}
public void ShowSetupPage ()
{
if (ChangePageEvent != null)
@ -201,11 +184,26 @@ namespace SparkleShare {
}
public void AddPageCompleted (string server, string folder_name)
public void ShowAddPage ()
{
this.syncing_folder = Path.GetFileNameWithoutExtension (folder_name);
this.previous_server = server;
this.previous_folder = folder_name;
if (ChangePageEvent != null)
ChangePageEvent (PageType.Add);
int index;
if (SelectedPlugin == null)
index = 0;
else
index = Plugins.IndexOf (SelectedPlugin);
SelectedPluginChanged (SelectedPluginIndex);
}
public void AddPageCompleted (string address, string path)
{
this.syncing_folder = Path.GetFileNameWithoutExtension (path);
this.previous_address = address;
this.previous_path = path;
if (ChangePageEvent != null)
ChangePageEvent (PageType.Syncing);
@ -214,7 +212,10 @@ namespace SparkleShare {
if (ChangePageEvent != null)
ChangePageEvent (PageType.Finished);
this.syncing_folder = "";
this.previous_address = "";
this.syncing_folder = "";
this.previous_url = "";
SelectedPlugin = Plugins [0];
};
Program.Controller.FolderFetchError += delegate (string remote_url) {
@ -231,7 +232,7 @@ namespace SparkleShare {
UpdateProgressBarEvent (percentage);
};
Program.Controller.FetchFolder (server, folder_name);
Program.Controller.FetchFolder (address, path);
}
@ -253,8 +254,8 @@ namespace SparkleShare {
public void FinishedPageCompleted ()
{
this.previous_server = "";
this.previous_folder = "";
this.previous_address = "";
this.previous_path = "";
Program.Controller.UpdateState ();
}
@ -265,27 +266,27 @@ namespace SparkleShare {
if (SelectedPlugin.Address != null) {
if (ChangeAddressFieldEvent != null)
ChangeAddressFieldEvent (SelectedPlugin.Address, null, FieldState.Disabled);
ChangeAddressFieldEvent (SelectedPlugin.Address, "", FieldState.Disabled);
} else if (SelectedPlugin.AddressExample != null) {
if (ChangeAddressFieldEvent != null)
ChangeAddressFieldEvent (PreviousServer, SelectedPlugin.AddressExample, FieldState.Enabled);
ChangeAddressFieldEvent ("", SelectedPlugin.AddressExample, FieldState.Enabled);
} else {
if (ChangeAddressFieldEvent != null)
ChangeAddressFieldEvent (PreviousServer, SelectedPlugin.AddressExample, FieldState.Enabled);
ChangeAddressFieldEvent ("", "", FieldState.Enabled);
}
if (SelectedPlugin.Path != null) {
if (ChangePathFieldEvent != null)
ChangePathFieldEvent (SelectedPlugin.Path, null, FieldState.Disabled);
ChangePathFieldEvent (SelectedPlugin.Path, "", FieldState.Disabled);
} else if (SelectedPlugin.PathExample != null) {
if (ChangePathFieldEvent != null)
ChangePathFieldEvent (PreviousFolder, SelectedPlugin.PathExample, FieldState.Enabled);
ChangePathFieldEvent ("", SelectedPlugin.PathExample, FieldState.Enabled);
} else {
if (ChangePathFieldEvent != null)
ChangePathFieldEvent (PreviousFolder, SelectedPlugin.PathExample, FieldState.Enabled);
ChangePathFieldEvent ("", "", FieldState.Enabled);
}
// TODO: previous server/folder doesn't work yet

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<sparkleshare>
<plugin>
<info>
<_name>Red Hat UX Team Hub</_name>
<_description>Internal server for the UX team</_description>
<icon>redhat.png</icon>
<backend>Git</backend>
</info>
<address>
<value>ssh://git@design.bos.lab.redhat.com/</value>
<example></example>
</address>
<path>
<value></value>
<_example>/project</_example>
</path>
</plugin>
</sparkleshare>