44 Commits
v0.4 ... v0.5.2

Author SHA1 Message Date
abdelkader
47e5f0406f added UIToolbox to add removable component
start
2023-06-27 12:32:38 -04:00
abdelkader
cbc4a24152 Merge branch 'master' of https://github.com/abdelkader/vCardEditor 2023-06-27 12:32:26 -04:00
Abdel
2c47765a5e Update README.md 2023-06-12 22:50:59 -04:00
abdelkader
f538d3a978 remove test 2023-05-11 08:56:35 -04:00
abdelkader
a589c642d3 Merge branch 'master' of https://github.com/abdelkader/vCardEditor 2023-05-11 08:56:13 -04:00
Abdel
687b2a248a Update README.md 2023-05-11 08:53:39 -04:00
abdelkader
834c1a7243 Added test and refactor 2023-05-10 13:20:17 -04:00
abdelkader
d9657f2318 Added test 2023-05-09 22:08:49 -04:00
abdelkader
3bbe7170c4 added autofixture et other tests 2023-05-09 20:41:33 -04:00
abdelkader
48631de425 refacotring
added tests
2023-05-09 19:42:31 -04:00
abdelkader
71b5b7580a Merge branch 'master' of https://github.com/abdelkader/vCardEditor 2023-05-08 21:56:13 -04:00
abdelkader
7a4c8e9d42 fix minor fusions commit 2023-05-08 21:54:33 -04:00
abdelkader
1233425972 refactor 2023-05-08 21:43:23 -04:00
abdelkader
2885f5f5cc fusion 2023-05-08 19:57:21 -04:00
abdelkader
89c06504ee first draft of adding column
added a split container
save position and location of winform
save also visible columns
Added vcard copy to clipboard
corrected failed tests
2023-05-08 19:53:12 -04:00
Abdel
adac378b13 Update README.md 2023-05-05 17:56:07 -04:00
abdelkader
74b5400a34 Added vcard copy to clipboard 2023-05-04 21:22:37 -04:00
abdelkader
7ffb330559 corrected failed tests 2023-05-04 18:30:07 -04:00
abdelkader
3b1cfcd36b added a release file 2023-05-04 15:28:42 -04:00
Abdel
8cf9ce829c Update README.md 2023-05-04 14:36:39 -04:00
Abdel
071c967e08 Update README.md
added the screenshot
2023-05-04 14:34:35 -04:00
Abdel
618e341e02 Update README.md 2023-05-04 13:59:19 -04:00
abdelkader
6427542051 possibility to modify address type 2023-05-04 13:52:10 -04:00
abdelkader
dc9fa3143a Merge branch 'master' of https://github.com/abdelkader/vCardEditor 2023-05-03 21:12:50 -04:00
abdelkader
f0742c560c fusion 2023-05-03 21:08:37 -04:00
abdelkader
e4e6a983e3 Support adding/removing multiple addresses 2023-05-03 21:01:06 -04:00
Abdel
f4ede0585b Merge pull request #28 from abdelkader/abdelkader-patch-1
Update README.md
2023-04-30 12:04:34 -04:00
Abdel
83cda3c073 Update README.md 2023-04-30 12:03:30 -04:00
Abdel
8d9070f483 Update README.md 2023-04-19 17:27:07 -04:00
Abdel
4b33a2425d Update README.md 2023-04-19 17:22:17 -04:00
Abdel
fa7f2c85d2 Update README.md 2023-04-19 15:15:57 -04:00
Abdel
a40ffaca58 Update README.md 2023-04-19 15:05:43 -04:00
abdelkader
2325b5f986 file extension capital letter 2023-04-14 17:52:18 -04:00
abdelkader
1db99cf187 extension capital letter 2023-04-14 17:52:02 -04:00
abdelkader
fe4c6381da first working draft 2023-04-14 12:07:42 -04:00
abdelkader
437301d5bc Draft of export image 2023-04-09 17:21:40 -04:00
abdelkader
ed4d988c1d Merge branch 'master' into export-img 2023-04-06 23:51:40 -04:00
abdelkader
b249d91439 added test to incorrect vcf file 2023-04-06 23:50:46 -04:00
abdelkader
7d9bfc4fe3 draft of export image 2023-04-06 23:27:12 -04:00
abdelkader
62deb9a13e support for empty vcf file 2023-04-06 15:56:31 -04:00
abdelkader
4081142e2c refactoring 2023-04-06 15:35:20 -04:00
abdelkader
dd62810160 refactoring 2023-04-06 13:50:32 -04:00
abdelkader
314065c2dc fixed mru problem 2023-04-03 12:14:18 -04:00
abdelkader
a5e932b345 issue #15 2023-04-03 11:14:54 -04:00
64 changed files with 4305 additions and 1111 deletions

1
.gitignore vendored
View File

@@ -216,3 +216,4 @@ FakesAssemblies/
**/*.Server/ModelManifest.xml
_Pvt_Extensions
/contacts
/vCardEditor/assests/icons8-save-32.png

View File

@@ -1,40 +1,35 @@
# vCard Editor
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/B0B2KV8WP)
<a href="https://github.com/abdelkader/vCardEditor/releases/latest/download/vCardEditor.exe"><img src="https://camo.githubusercontent.com/d83fa798b621f1e112646fcc4aa74fff1ff6a8b22f5fc1da5ed8f79ddb4a51cb/68747470733a2f2f62616467656e2e6e65742f6769746875622f72656c656173652f4e61657265656e2f5374726170646f776e2e6a73" alt="Latest release" data-canonical-src="https://badgen.net/github/release/Naereen/Strapdown.js" style="max-width: 100%;"></a>
## vCard Editor
A Simple vcf file Editor. You can export easily edit (modify, delete) entries of a vcf file with this simple tool.
The software is still in **early stage**.
<p align="center"><img src="https://user-images.githubusercontent.com/169070/236289228-106c1489-e01d-400c-968e-92d3e2be74ab.png" width="800"></p>
## Installation
## ✅ Features
- [x] No need to install anything. Just head to the release section and download the last release version.
- [x] Add/Export images
No need to install anything. Just head to the release section and download the last release version.
## Screenshots
![App Screenshot](https://user-images.githubusercontent.com/474542/151180600-cf169628-0761-49a9-a63d-05f751c6a9bb.png)
## Acknowledgements
- [Wonderful library of parsing and generating vcf format](https://github.com/drlongnecker/Thought.vCards)
- [MVP pattern from this example](https://github.com/lennykean/NoteCards)
## Release notes
#### 0.3
- Added address section.
- refactoring and bugs fixed
#### 0.2
- Updated the vCard library to https://github.com/acastroy/Thought.vCards
- Replaced Moq with nsubstitute (Test mocking library).
## Contributing
Contributions are always welcome!
## 📚 Tech Stack
- 🧰 [Wonderful library of parsing and generating vcf format](https://github.com/drlongnecker/Thought.vCards)
- 📖 [MVP pattern from this example](https://github.com/lennykean/NoteCards)
- 🧰 [SortableBindingList](http://timvw.be/2008/08/02/presenting-the-sortablebindinglistt-take-two/)
- 🧰 [Custom TabControl](https://github.com/r-aghaei/TabControlWithCloseButtonAndAddButton)
## 📑 Release notes
Check release text file for history.
## 👷 Contributing
Contributions are always welcome! Check ths projet or ths issue page for ideas.

View File

@@ -0,0 +1,9 @@
namespace vCardEditor.Model
{
public enum Column
{
Name = 0,
FamilyName,
Cellular,
}
}

View File

@@ -3,23 +3,32 @@ using Thought.vCards;
namespace VCFEditor.Model
{
/// <summary>
///
/// </summary>
public class Contact : INotifyPropertyChanged
{
[DisplayName(" ")]
public bool isSelected { get; set; }
[DisplayName("Name")]
public string Name
{
get { return card.FormattedName; }
get => card.FormattedName;
set
{
card.FormattedName = value;
this.NotifyPropertyChanged("Name");
NotifyPropertyChanged("Name");
}
}
[DisplayName("F.Name")]
public string FamilyName
{
get => card.FamilyName;
}
[DisplayName("Cellular")]
public string Cellular
{
get {
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
return card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber;
return string.Empty;
}
}
@@ -29,7 +38,10 @@ namespace VCFEditor.Model
[Browsable(false)]
public bool isDirty { get; set; }
[DisplayName(" ")]
public bool isSelected { get; set; }
[Browsable(false)]
public bool isDeleted { get; set; }
@@ -41,14 +53,11 @@ namespace VCFEditor.Model
isDirty = false;
}
#region property change event
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace vCardEditor.Model
{
public struct FormState
{
public List<Column> Columns { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public int splitterPosition { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
namespace vCardEditor.Model
{
public class PropertyComparer<T> : IComparer<T>
{
private readonly IComparer comparer;
private PropertyDescriptor propertyDescriptor;
private int reverse;
public PropertyComparer(PropertyDescriptor property, ListSortDirection direction)
{
this.propertyDescriptor = property;
Type comparerForPropertyType = typeof(Comparer<>).MakeGenericType(property.PropertyType);
this.comparer = (IComparer)comparerForPropertyType.InvokeMember("Default", BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.Public, null, null, null);
this.SetListSortDirection(direction);
}
#region IComparer<T> Members
public int Compare(T x, T y)
{
return this.reverse * this.comparer.Compare(this.propertyDescriptor.GetValue(x), this.propertyDescriptor.GetValue(y));
}
#endregion
private void SetPropertyDescriptor(PropertyDescriptor descriptor)
{
this.propertyDescriptor = descriptor;
}
private void SetListSortDirection(ListSortDirection direction)
{
this.reverse = direction == ListSortDirection.Ascending ? 1 : -1;
}
public void SetPropertyAndDirection(PropertyDescriptor descriptor, ListSortDirection direction)
{
this.SetPropertyDescriptor(descriptor);
this.SetListSortDirection(direction);
}
}
}

View File

@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Thought.vCards;
using VCFEditor.View;
using vCardEditor.View;
using VCFEditor.Repository;
using vCardEditor.Repository;
using vCardEditor.Model;
using System.Linq;
using System.IO;
using System.Collections.Generic;
namespace VCFEditor.Presenter
{
@@ -21,98 +21,186 @@ namespace VCFEditor.Presenter
_view = view;
_repository = repository;
_view.AddContact += AddContact;
_view.NewFileOpened += NewFileOpened;
_view.BeforeOpeningNewFile += BeforeOpeningNewFile;
_view.SaveContactsSelected += SaveContacts;
_view.ChangeContactsSelected += ChangeContactSelected;
_view.DeleteContact += DeleteContact;
_view.FilterTextChanged += FilterTextChanged;
_view.TextBoxValueChanged += TextBoxValueChanged;
_view.BeforeLeavingContact += BeforeLeavingContact;
_view.CloseForm += CloseForm;
_view.LoadForm += LoadFormHandler;
_view.AddContact += AddContactHandler;
_view.NewFileOpened += NewFileOpenedHandler;
_view.BeforeOpeningNewFile += BeforeOpeningNewFileHandler;
_view.SaveContactsSelected += SaveContactsHandler;
_view.ChangeContactsSelected += ChangeContactSelectedHandler;
_view.DeleteContact += DeleteContactHandler;
_view.FilterTextChanged += FilterTextChangedHandler;
_view.TextBoxValueChanged += TextBoxValueChangedHandler;
_view.BeforeLeavingContact += BeforeLeavingContactHandler;
_view.CloseForm += CloseFormHandler;
_view.ModifyImage += ModifyImageHandler;
_view.ExportImage += ExportImageHandler;
_view.AddressAdded += AddressAddedHandler;
_view.AddressModified += AddressModifiedHandler;
_view.AddressRemoved += AddressRemovedHandler;
_view.CopyTextToClipboardEvent += CopyTextToClipboardHandler;
}
void CloseForm(object sender, EventArg<bool> e)
private void CopyTextToClipboardHandler(object sender, EventArgs e)
{
if (_repository.dirty && _view.AskMessage("Exit before saving?", "Exit"))
e.Data = true;
if (_view.SelectedContactIndex < 0)
return;
var contact = _repository.Contacts[_view.SelectedContactIndex];
string SerializedCard = _repository.GenerateStringFromVCard(contact.card);
_view.SendTextToClipBoard(SerializedCard);
_view.DisplayMessage("vCard copied to clipboard!", "Information");
}
public void BeforeLeavingContact(object sender, EventArg<vCard> e)
private void LoadFormHandler(object sender, EventArg<FormState> e)
{
if (_view.SelectedContactIndex > -1)
e.Data = ConfigRepository.Instance.FormState;
var paths = Environment.GetCommandLineArgs();
if (paths.Length > 1)
{
if (_repository.dirty)
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
var evt = new EventArg<string>(paths[1]);
NewFileOpenedHandler(sender, evt);
}
}
public void TextBoxValueChanged(object sender, EventArgs e)
private void AddressRemovedHandler(object sender, EventArg<int> e)
{
StateTextBox tb = sender as StateTextBox;
if (tb != null && tb.oldText != tb.Text)
_repository.SaveDirtyFlag(_view.SelectedContactIndex);
var contact = _repository.Contacts[_view.SelectedContactIndex];
_repository.SetDirtyFlag(_view.SelectedContactIndex);
contact.card.DeliveryAddresses.RemoveAt(e.Data);
}
private void AddressAddedHandler(object sender, EventArg<List<vCardDeliveryAddressTypes>> e)
{
var contact = _repository.Contacts[_view.SelectedContactIndex];
_repository.SetDirtyFlag(_view.SelectedContactIndex);
contact.card.DeliveryAddresses.Add(new vCardDeliveryAddress( e.Data));
}
private void AddressModifiedHandler(object sender, EventArg<List<vCardDeliveryAddressTypes>> e)
{
var contact = _repository.Contacts[_view.SelectedContactIndex];
_repository.SetDirtyFlag(_view.SelectedContactIndex);
contact.card.DeliveryAddresses.Clear();
contact.card.DeliveryAddresses.Add(new vCardDeliveryAddress(e.Data));
}
private void ExportImageHandler(object sender, EventArgs e)
{
if (_view.SelectedContactIndex > -1)
{
//TODO: image can be url, or file location.
var card = _repository.Contacts[_view.SelectedContactIndex].card;
var image = card.Photos.FirstOrDefault();
if (image != null)
{
var newPath = _repository.ChangeExtension(_repository.fileName, image.Extension);
string imageFile = _view.DisplaySaveDialog(newPath);
_repository.SaveImageToDisk(imageFile, image);
}
}
}
private void ModifyImageHandler(object sender, EventArg<string> e)
{
if (!string.IsNullOrEmpty(e.Data) )
{
vCardPhoto photo = new vCardPhoto(e.Data);
_repository.ModifyImage(_view.SelectedContactIndex, photo);
}
else
_repository.ModifyImage(_view.SelectedContactIndex, null);
}
public void FilterTextChanged(object sender, EventArg<string> e)
void CloseFormHandler(object sender, EventArg<bool> e)
{
if (_repository.dirty && _view.AskMessage("Exit without saving?", "Exit"))
e.Data = true;
if (!e.Data)
{
var state = _view.GetFormState();
ConfigRepository.Instance.FormState = state;
ConfigRepository.Instance.SaveConfig();
}
}
public void BeforeLeavingContactHandler(object sender, EventArg<vCard> e)
{
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
}
public void TextBoxValueChangedHandler(object sender, EventArgs e)
{
var tb = sender as StateTextBox;
if (tb != null && tb.oldText != tb.Text)
_repository.SetDirtyFlag(_view.SelectedContactIndex);
}
public void FilterTextChangedHandler(object sender, EventArg<string> e)
{
var FilteredContacts = _repository.FilterContacts(e.Data);
_view.DisplayContacts(FilteredContacts);
}
private void AddContact(object sender, EventArgs e)
private void AddContactHandler(object sender, EventArgs e)
{
_repository.AddEmptyContact();
}
private void DeleteContact(object sender, EventArgs e)
private void DeleteContactHandler(object sender, EventArgs e)
{
_repository.DeleteContact();
}
private void SaveContacts(object sender, EventArgs e)
private void SaveContactsHandler(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(_repository.fileName))
_repository.SaveContacts(_repository.fileName);
_repository.SaveContactsToFile(_repository.fileName);
}
private void BeforeOpeningNewFile(object sender, EventArgs e)
private void BeforeOpeningNewFileHandler(object sender, EventArgs e)
{
if (_repository.Contacts != null && _repository.dirty)
{
if (!_view.AskMessage("Save current file before?", "Load"))
_repository.SaveContacts(_repository.fileName);
_repository.SaveContactsToFile(_repository.fileName);
}
}
public void NewFileOpened(object sender, EventArg<string> e)
public void NewFileOpenedHandler(object sender, EventArg<string> e)
{
BeforeOpeningNewFile(sender, e);
BeforeOpeningNewFileHandler(sender, e);
string path = e.Data;
if (string.IsNullOrEmpty(path))
path = _view.DisplayOpenDialog();
path = _view.DisplayOpenDialog("vCard Files|*.vcf");
if (!string.IsNullOrEmpty(path))
{
string ext = System.IO.Path.GetExtension(path);
if (ext != ".vcf")
string ext = _repository.GetExtension(path);
if (!string.Equals(ext, ".vcf", StringComparison.OrdinalIgnoreCase))
{
_view.DisplayMessage("Only vcf extension accepted!", "Error");
return;
}
FixedList MRUList = ConfigRepository.Instance.Paths;
if (!MRUList.Contains(path))
FixedList MostRecentUsedFiles = ConfigRepository.Instance.Paths;
if (!MostRecentUsedFiles.Contains(path))
{
MRUList.Enqueue(path);
_view.UpdateMRUMenu(MRUList);
MostRecentUsedFiles.Enqueue(path);
_view.UpdateMRUMenu(MostRecentUsedFiles);
}
_repository.LoadContacts(path);
@@ -122,23 +210,21 @@ namespace VCFEditor.Presenter
}
public void ChangeContactSelected(object sender, EventArgs e)
public void ChangeContactSelectedHandler(object sender, EventArgs e)
{
if (_view.SelectedContactIndex > -1)
{
int index = _view.SelectedContactIndex;
vCard card = _repository.Contacts[index].card;
vCard card = _repository.Contacts[_view.SelectedContactIndex].card;
if (card != null)
{
_repository.Contacts[index].isDirty = false;
_view.DisplayContactDetail(card, _repository.fileName);
}
else
_view.ClearContactDetail();
}
else
_view.ClearContactDetail();
}
}
}

View File

@@ -19,7 +19,7 @@ namespace vCardEditor.Properties {
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
// avec l'option /str ou régénérez votre projet VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -59,5 +59,25 @@ namespace vCardEditor.Properties {
resourceCulture = value;
}
}
/// <summary>
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Add {
get {
object obj = ResourceManager.GetObject("Add", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Close {
get {
object obj = ResourceManager.GetObject("Close", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@@ -117,4 +117,11 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\assests\Add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Close" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\assests\Close.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

17
vCardEditor/Releases.txt Normal file
View File

@@ -0,0 +1,17 @@
0.5
A reworked control for adding/modifying or removing addresses.
0.4
Import images/export images.
refactoring and bugs fixed
0.3
Added address section.
refactoring and bugs fixed
0.2
Updated the vCard library to https://github.com/acastroy/Thought.vCards
Replaced Moq with nsubstitute (Test mocking library).
0.1
Intial release

View File

@@ -1,22 +1,21 @@
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel;
using vCardEditor.Model;
using System.Runtime.Serialization;
namespace vCardEditor.Repository
{
[XmlRoot("Config")]
[Serializable]
public class ConfigRepository
public class ConfigRepository : IConfigRepository
{
private static string ConfigFileName
{
get { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.xml"); }
}
private const int MAX_RECENT_FILES = 5;
private static ConfigRepository instance = null;
[XmlIgnore]
public static ConfigRepository Instance
@@ -36,7 +35,10 @@ namespace vCardEditor.Repository
public int Maximum { get; set; }
[Browsable(false)]
public FixedList Paths { get; set;}
public FixedList Paths { get; set; }
[Browsable(false)]
public FormState FormState;
private ConfigRepository() { }
@@ -64,7 +66,7 @@ namespace vCardEditor.Repository
/// <returns></returns>
private static ConfigRepository LoadConfig()
{
ConfigRepository obj;
ConfigRepository configData = null;
try
{
@@ -74,21 +76,24 @@ namespace vCardEditor.Repository
XmlSerializer deserializer = new XmlSerializer(typeof(ConfigRepository));
using (TextReader reader = new StreamReader(ConfigFileName))
{
obj = (ConfigRepository)deserializer.Deserialize(reader);
obj.Paths.Size = obj.Maximum;
configData = (ConfigRepository)deserializer.Deserialize(reader);
configData.Paths.Size = configData.Maximum;
}
}
catch (Exception)
{
obj = new ConfigRepository();
obj.Paths = new FixedList(5);
configData = new ConfigRepository
{
Maximum = MAX_RECENT_FILES,
Paths = new FixedList(MAX_RECENT_FILES)
};
}
return obj;
return configData;
}
}
}

View File

@@ -6,7 +6,7 @@ using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.Repository;
using System.Collections.Generic;
using vCardEditor.View;
namespace VCFEditor.Repository
{
@@ -14,7 +14,6 @@ namespace VCFEditor.Repository
{
public string fileName { get; set; }
private IFileHandler _fileHandler;
#region Contact Info
/// <summary>
/// Formatted name.
/// </summary>
@@ -23,17 +22,14 @@ namespace VCFEditor.Repository
/// <summary>
/// Keep a copy of contact list when filtering
/// </summary>
private BindingList<Contact> OriginalContactList = null;
/// <summary>
/// Contact List
/// </summary>
private BindingList<Contact> _contacts;
public BindingList<Contact> Contacts
private SortableBindingList<Contact> OriginalContactList = null;
private SortableBindingList<Contact> _contacts;
public SortableBindingList<Contact> Contacts
{
get
{
if (_contacts == null)
_contacts = new BindingList<Contact>();
_contacts = new SortableBindingList<Contact>();
return _contacts;
}
set
@@ -41,29 +37,32 @@ namespace VCFEditor.Repository
_contacts = value;
}
}
#endregion
private bool _dirty;
public bool dirty
{
get { return (_contacts != null && _contacts.Any(x => x.isDirty)) || _dirty; }
set { _dirty = true; }
}
public ContactRepository(IFileHandler fileHandler)
{
_fileHandler = fileHandler;
}
public BindingList<Contact> LoadContacts(string fileName)
public SortableBindingList<Contact> LoadContacts(string fileName)
{
Contacts.Clear();
this.fileName = fileName;
string[] lines = _fileHandler.ReadAllLines(fileName);
StringBuilder RawContent = new StringBuilder();
Contact contact = new Contact();
string[] lines = _fileHandler.ReadAllLines(fileName);
//TODO: Clean end of line from spaces..
//Prevent from adding contacts to existings ones.
Contacts.Clear();
for (int i = 0; i < lines.Length; i++)
{
RawContent.AppendLine(lines[i]);
if (lines[i].TrimEnd() == "END:VCARD")
if (string.Equals(lines[i].TrimEnd(), "END:VCARD", StringComparison.OrdinalIgnoreCase))
{
contact.card = ParseRawContent(RawContent);
Contacts.Add(contact);
@@ -72,14 +71,11 @@ namespace VCFEditor.Repository
}
}
OriginalContactList = Contacts;
_dirty = false;
return Contacts;
}
/// <summary>
/// Add a new empty contact
/// </summary>
public void AddEmptyContact()
{
if (_contacts != null && _contacts.Count > 0)
@@ -89,17 +85,13 @@ namespace VCFEditor.Repository
}
}
/// <summary>
/// Save the contact to the file.
/// </summary>
/// <param name="path">Path to the new file, else if null, we overwrite the same file</param>
public void SaveContacts(string fileName)
public void SaveContactsToFile(string fileName)
{
//overwrite the same file, else save as another file.
if (string.IsNullOrEmpty(fileName))
fileName = this.fileName;
//Take a copy...
//Take a copy if specified in the config file
if (!ConfigRepository.Instance.OverWrite)
{
string backupName = GetBackupName();
@@ -107,17 +99,22 @@ namespace VCFEditor.Repository
}
StringBuilder sb = new StringBuilder();
//Do not save the deleted ones...
foreach (var entry in Contacts)
{
//Do not save the deleted ones!
if (!entry.isDeleted)
sb.Append(generateRawContent(entry.card));
{
string SerializedCard = GenerateStringFromVCard(entry.card);
sb.Append(SerializedCard);
}
//Clean the flag for every contact, even the deleted ones.
entry.isDirty = false;
}
_fileHandler.WriteAllText(fileName, sb.ToString());
_dirty = false;
}
private string GetBackupName()
@@ -133,37 +130,25 @@ namespace VCFEditor.Repository
return backupName;
}
/// <summary>
/// Delete contacted that are selected.
/// </summary>
public void DeleteContact()
{
if (_contacts != null && _contacts.Count > 0)
{
//loop from the back to prevent index mangling...
for (int i = _contacts.Count - 1; i > -1; i--)
{
if (_contacts[i].isSelected)
{
_contacts[i].isDeleted = true;
_contacts.RemoveAt(i);
_dirty = true;
_contacts.RemoveAt(i);
}
}
}
}
/// <summary>
/// Use the lib to parse a vcard chunk.
/// </summary>
/// <param name="rawContent"></param>
/// <returns></returns>
private vCard ParseRawContent(StringBuilder rawContent)
{
vCard card = null;
@@ -176,12 +161,7 @@ namespace VCFEditor.Repository
return card;
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
@@ -192,21 +172,16 @@ namespace VCFEditor.Repository
return stream;
}
public BindingList<Contact> FilterContacts(string filter)
public SortableBindingList<Contact> FilterContacts(string filter)
{
var list = OriginalContactList.Where(i => (i.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) &&
!i.isDeleted);
Contacts = new BindingList<Contact>(list.ToList());
Contacts = new SortableBindingList<Contact>(list.ToList());
return Contacts;
}
/// <summary>
/// Save modified card info in the raw content.
/// </summary>
/// <param name="card"></param>
/// <param name="index"></param>
public void SaveDirtyFlag(int index)
public void SetDirtyFlag(int index)
{
if (index > -1)
_contacts[index].isDirty = true;
@@ -228,9 +203,6 @@ namespace VCFEditor.Repository
SaveEmail(NewCard, card);
SaveWebUrl(NewCard, card);
SaveAddresses(NewCard, card);
_contacts[index].isDirty = false;
_dirty = false;
}
}
@@ -251,7 +223,6 @@ namespace VCFEditor.Repository
card.DeliveryAddresses.Add(new vCardDeliveryAddress(item.Street, item.City, item.Region, item.Country,
item.PostalCode, item.AddressType.FirstOrDefault()));
}
}
@@ -357,12 +328,8 @@ namespace VCFEditor.Repository
}
}
/// <summary>
/// Generate a VCard class from a string.
/// </summary>
/// <param name="card"></param>
/// <returns></returns>
private string generateRawContent(vCard card)
public string GenerateStringFromVCard(vCard card)
{
vCardStandardWriter writer = new vCardStandardWriter();
TextWriter tw = new StringWriter();
@@ -371,19 +338,33 @@ namespace VCFEditor.Repository
return tw.ToString();
}
/// <summary>
/// Check if some item in the contact list is modified
/// Every contact has a dirty flag, and also there's a global dirty flag (used when contact is deleted!)
/// </summary>
/// <returns>true for dirty</returns>
private bool _dirty;
public bool dirty
public void ModifyImage(int index, vCardPhoto photo)
{
get { return _dirty || (_contacts != null && _contacts.Any(x => x.isDirty)); }
set { _dirty = value; }
if (index > -1)
{
SetDirtyFlag(index);
_contacts[index].card.Photos.Clear();
if (photo != null)
_contacts[index].card.Photos.Add(photo);
}
}
public string GetExtension(string path)
{
return _fileHandler.GetExtension(path);
}
public void SaveImageToDisk(string imageFile, vCardPhoto image)
{
_fileHandler.WriteBytesToFile(imageFile, image.GetBytes());
}
public string ChangeExtension(string path, string extension)
{
return _fileHandler.ChangeExtension(path, extension);
}
}
}

View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.IO;
namespace vCardEditor.Repository
{
@@ -13,6 +10,16 @@ namespace vCardEditor.Repository
return File.Exists(filename);
}
public string GetExtension(string path)
{
return Path.GetExtension(path);
}
public string ChangeExtension(string path, string extension)
{
return Path.ChangeExtension(path, extension);
}
public void MoveFile(string newFilename, string oldFilename)
{
File.Move(newFilename, oldFilename);
@@ -27,5 +34,14 @@ namespace vCardEditor.Repository
{
File.WriteAllText(filename, contents);
}
public void WriteBytesToFile(string imageFile, byte[] image)
{
using (var ms = new MemoryStream(image))
{
using (var fs = new FileStream(imageFile, FileMode.Create))
ms.WriteTo(fs);
}
}
}
}

View File

@@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
namespace VCFEditor.Repository
{
public interface IContactRepository
{
string fileName { get; set; }
BindingList<Contact> Contacts { get; set; }
bool dirty { get; set; }
BindingList<Contact> LoadContacts(string fileName);
void SaveContacts(string fileName);
void DeleteContact();
BindingList<Contact> FilterContacts(string p);
void SaveDirtyFlag(int index);
void SaveDirtyVCard(int index, vCard card);
void AddEmptyContact();
}
}

View File

@@ -0,0 +1,13 @@
using vCardEditor.Model;
namespace vCardEditor.Repository
{
public interface IConfigRepository
{
int Maximum { get; set; }
bool OverWrite { get; set; }
FixedList Paths { get; set; }
void SaveConfig();
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.View;
namespace VCFEditor.Repository
{
public interface IContactRepository
{
bool dirty { get; }
string fileName { get; set; }
SortableBindingList<Contact> Contacts { get; set; }
SortableBindingList<Contact> LoadContacts(string fileName);
SortableBindingList<Contact> FilterContacts(string p);
void SaveContactsToFile(string fileName);
void DeleteContact();
void SetDirtyFlag(int index);
void SaveDirtyVCard(int index, vCard card);
void AddEmptyContact();
void ModifyImage(int index, vCardPhoto photo);
string GetExtension(string path);
string ChangeExtension(string path, string extension);
void SaveImageToDisk(string imageFile, vCardPhoto image);
string GenerateStringFromVCard(vCard card);
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace vCardEditor.Repository
namespace vCardEditor.Repository
{
public interface IFileHandler
{
@@ -11,5 +6,8 @@ namespace vCardEditor.Repository
bool FileExist(string filename);
string[] ReadAllLines(string filename);
void WriteAllText(string fileName, string contents);
string GetExtension(string path);
string ChangeExtension(string path, string extension);
void WriteBytesToFile(string imageFile, byte[] image);
}
}

View File

@@ -25,6 +25,8 @@ namespace Thought.vCards
private string postalCode;
private string region;
private string street;
private string postOfficeBox;
private string extendedAddress;
/// <summary>
@@ -37,6 +39,8 @@ namespace Thought.vCards
this.postalCode = string.Empty;
this.region = string.Empty;
this.street = string.Empty;
this.postOfficeBox = string.Empty;
this.extendedAddress = string.Empty;
this.addressType = new List<vCardDeliveryAddressTypes>();
}
@@ -50,7 +54,22 @@ namespace Thought.vCards
Street = street;
}
public vCardDeliveryAddress(string street, string city, string region, string country, string postalCode, string extendedAddress, string postOfficeBox, vCardDeliveryAddressTypes addressType)
{
AddressType = new List<vCardDeliveryAddressTypes>() { addressType };
City = city;
Country = country;
PostalCode = postalCode;
Region = region;
Street = street;
ExtendedAddress = extendedAddress;
PostOfficeBox= postOfficeBox;
}
public vCardDeliveryAddress(List<vCardDeliveryAddressTypes> addressType)
{
AddressType = addressType ;
}
/// <summary>
/// The type of postal address.
@@ -230,6 +249,28 @@ namespace Thought.vCards
}
}
public string ExtendedAddress
{
get
{
return this.extendedAddress ?? string.Empty;
}
set
{
this.extendedAddress = value;
}
}
public string PostOfficeBox
{
get
{
return this.postOfficeBox ?? string.Empty;
}
set
{
this.postOfficeBox = value;
}
}
}
}

View File

@@ -48,7 +48,7 @@ namespace Thought.vCards
/// </summary>
private Uri url;
public string Extension { get; }
private string encodedData;
@@ -60,12 +60,13 @@ namespace Thought.vCards
/// An array of bytes containing the raw data from
/// any of the supported image formats.
/// </param>
public vCardPhoto(byte[] buffer)
public vCardPhoto(byte[] buffer, string imageType)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
this.data = (byte[])buffer.Clone();
this.Extension = imageType;
}
@@ -75,13 +76,14 @@ namespace Thought.vCards
/// <param name="url">
/// A URL pointing to an image.
/// </param>
public vCardPhoto(Uri url)
public vCardPhoto(Uri url, string imageType)
{
if (url == null)
throw new ArgumentNullException("url");
this.url = url;
this.Extension = imageType;
}
@@ -110,7 +112,7 @@ namespace Thought.vCards
/// <param name="isEncoded">
/// Boolean true if is encoded.
/// </param>
public vCardPhoto(string data, bool isEncoded)
public vCardPhoto(string data, bool isEncoded, string imageType)
{
if (string.IsNullOrEmpty(data))
@@ -119,7 +121,7 @@ namespace Thought.vCards
}
this.encodedData = data;
this.Extension = imageType;
}
@@ -291,6 +293,7 @@ namespace Thought.vCards
}
}
/// <summary>
/// The URL of the image.

View File

@@ -1225,6 +1225,12 @@ namespace Thought.vCards
if (addressParts.Length >= 3)
deliveryAddress.Street = addressParts[2].Trim();
if (addressParts.Length >= 1)
deliveryAddress.ExtendedAddress = addressParts[1].Trim();
if (addressParts.Length >= 0)
deliveryAddress.PostOfficeBox = addressParts[0].Trim();
if (
(string.IsNullOrEmpty(deliveryAddress.City)) &&
(string.IsNullOrEmpty(deliveryAddress.Country)) &&
@@ -1661,6 +1667,7 @@ namespace Thought.vCards
// often consist of binary data.
vCardCertificate certificate = new vCardCertificate();
certificate.Data = (byte[])property.Value;
// TODO: Support other key types.
@@ -1900,6 +1907,8 @@ namespace Thought.vCards
private void ReadInto_PHOTO(vCard card, vCardProperty property)
{
string imageType = property.Subproperties.GetValue("TYPE");
// The PHOTO property contains an embedded (encoded) image
// or a link to an image. A URL (linked) image is supposed
// to be indicated with the VALUE=URI subproperty.
@@ -1914,7 +1923,7 @@ namespace Thought.vCards
// rather than being encoded directly in the vCard.
card.Photos.Add(
new vCardPhoto(new Uri(property.ToString())));
new vCardPhoto(new Uri(property.ToString()), imageType));
}
@@ -1922,13 +1931,15 @@ namespace Thought.vCards
{
if (property.Value.GetType() == typeof(string))
{
card.Photos.Add(new vCardPhoto((string)property.Value, true));
card.Photos.Add(new vCardPhoto((string)property.Value, true, imageType));
}
else
{
card.Photos.Add(new vCardPhoto((byte[])property.Value));
card.Photos.Add(new vCardPhoto((byte[])property.Value, imageType));
}
}
}

View File

@@ -1020,8 +1020,10 @@ namespace Thought.vCards
if (doEmbedded)
{
properties.Add(
new vCardProperty("PHOTO", photo.GetBytes()));
var EmbeddedProperty = new vCardProperty("PHOTO", photo.GetBytes());
EmbeddedProperty.Subproperties.Add("TYPE", "JPG");
properties.Add(EmbeddedProperty);
}
else
{

View File

@@ -54,7 +54,7 @@
this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5);
this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel.Location = new System.Drawing.Point(12, 11);
this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4);
this.tableLayoutPanel.Name = "tableLayoutPanel";
this.tableLayoutPanel.RowCount = 6;
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
@@ -73,7 +73,7 @@
//
this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image")));
this.logoPictureBox.Location = new System.Drawing.Point(4, 4);
this.logoPictureBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.logoPictureBox.Margin = new System.Windows.Forms.Padding(4);
this.logoPictureBox.Name = "logoPictureBox";
this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6);
this.logoPictureBox.Size = new System.Drawing.Size(145, 121);
@@ -148,7 +148,7 @@
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.okButton.Location = new System.Drawing.Point(452, 295);
this.okButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.okButton.Margin = new System.Windows.Forms.Padding(4);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(100, 27);
this.okButton.TabIndex = 24;
@@ -162,7 +162,7 @@
this.ClientSize = new System.Drawing.Size(580, 348);
this.Controls.Add(this.tableLayoutPanel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.Margin = new System.Windows.Forms.Padding(4);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AboutDialog";

View File

@@ -35,41 +35,45 @@
//
// btnClose
//
this.btnClose.Location = new System.Drawing.Point(253, 347);
this.btnClose.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnClose.Location = new System.Drawing.Point(337, 427);
this.btnClose.Margin = new System.Windows.Forms.Padding(4);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(75, 23);
this.btnClose.Size = new System.Drawing.Size(100, 28);
this.btnClose.TabIndex = 0;
this.btnClose.Text = "Close";
this.btnClose.UseVisualStyleBackColor = true;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// pgConfig
//
this.pgConfig.Location = new System.Drawing.Point(12, 12);
this.pgConfig.Location = new System.Drawing.Point(16, 15);
this.pgConfig.Margin = new System.Windows.Forms.Padding(4);
this.pgConfig.Name = "pgConfig";
this.pgConfig.Size = new System.Drawing.Size(316, 329);
this.pgConfig.Size = new System.Drawing.Size(421, 405);
this.pgConfig.TabIndex = 1;
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(172, 347);
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(229, 427);
this.btnCancel.Margin = new System.Windows.Forms.Padding(4);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.Size = new System.Drawing.Size(100, 28);
this.btnCancel.TabIndex = 0;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// ConfigDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(337, 382);
this.ClientSize = new System.Drawing.Size(449, 470);
this.Controls.Add(this.pgConfig);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnClose);
this.Margin = new System.Windows.Forms.Padding(4);
this.Name = "ConfigDialog";
this.Text = "ConfigDialog";
this.Text = "Configuration Dialog";
this.ResumeLayout(false);
}

View File

@@ -10,19 +10,8 @@ namespace vCardEditor.View
public ConfigDialog()
{
InitializeComponent();
ConfigRepository conf = ConfigRepository.Instance;//.Clone();
ConfigRepository conf = ConfigRepository.Instance;//
pgConfig.SelectedObject = conf;
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
}
}

View File

@@ -112,9 +112,9 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,165 @@

namespace vCardEditor.View.Customs
{
partial class AddAddressDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.cbHome = new System.Windows.Forms.CheckBox();
this.cbWork = new System.Windows.Forms.CheckBox();
this.cbPostal = new System.Windows.Forms.CheckBox();
this.cbDomestic = new System.Windows.Forms.CheckBox();
this.btnOK = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.cbInternational = new System.Windows.Forms.CheckBox();
this.cbCustom = new System.Windows.Forms.CheckBox();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// cbHome
//
this.cbHome.AutoSize = true;
this.cbHome.Location = new System.Drawing.Point(12, 12);
this.cbHome.Name = "cbHome";
this.cbHome.Size = new System.Drawing.Size(67, 21);
this.cbHome.TabIndex = 0;
this.cbHome.Text = "Home";
this.cbHome.UseVisualStyleBackColor = true;
//
// cbWork
//
this.cbWork.AutoSize = true;
this.cbWork.Location = new System.Drawing.Point(12, 40);
this.cbWork.Name = "cbWork";
this.cbWork.Size = new System.Drawing.Size(63, 21);
this.cbWork.TabIndex = 1;
this.cbWork.Text = "Work";
this.cbWork.UseVisualStyleBackColor = true;
//
// cbPostal
//
this.cbPostal.AutoSize = true;
this.cbPostal.Location = new System.Drawing.Point(12, 67);
this.cbPostal.Name = "cbPostal";
this.cbPostal.Size = new System.Drawing.Size(69, 21);
this.cbPostal.TabIndex = 2;
this.cbPostal.Text = "Postal";
this.cbPostal.UseVisualStyleBackColor = true;
//
// cbDomestic
//
this.cbDomestic.AutoSize = true;
this.cbDomestic.Location = new System.Drawing.Point(12, 94);
this.cbDomestic.Name = "cbDomestic";
this.cbDomestic.Size = new System.Drawing.Size(88, 21);
this.cbDomestic.TabIndex = 3;
this.cbDomestic.Text = "Domestic";
this.cbDomestic.UseVisualStyleBackColor = true;
//
// btnOK
//
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.Location = new System.Drawing.Point(95, 187);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(75, 23);
this.btnOK.TabIndex = 7;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// btnCancel
//
this.btnCancel.CausesValidation = false;
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(176, 187);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 8;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// cbInternational
//
this.cbInternational.AutoSize = true;
this.cbInternational.Location = new System.Drawing.Point(12, 121);
this.cbInternational.Name = "cbInternational";
this.cbInternational.Size = new System.Drawing.Size(108, 21);
this.cbInternational.TabIndex = 9;
this.cbInternational.Text = "International";
this.cbInternational.UseVisualStyleBackColor = true;
//
// cbCustom
//
this.cbCustom.AutoSize = true;
this.cbCustom.Location = new System.Drawing.Point(12, 148);
this.cbCustom.Name = "cbCustom";
this.cbCustom.Size = new System.Drawing.Size(81, 21);
this.cbCustom.TabIndex = 10;
this.cbCustom.Text = "Custom:";
this.cbCustom.UseVisualStyleBackColor = true;
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(90, 149);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(161, 22);
this.textBox1.TabIndex = 11;
//
// AddAddress
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(263, 223);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.cbCustom);
this.Controls.Add(this.cbInternational);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.cbDomestic);
this.Controls.Add(this.cbPostal);
this.Controls.Add(this.cbWork);
this.Controls.Add(this.cbHome);
this.Name = "AddAddress";
this.Text = "Address Type";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.CheckBox cbHome;
private System.Windows.Forms.CheckBox cbWork;
private System.Windows.Forms.CheckBox cbPostal;
private System.Windows.Forms.CheckBox cbDomestic;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.CheckBox cbInternational;
private System.Windows.Forms.CheckBox cbCustom;
private System.Windows.Forms.TextBox textBox1;
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Thought.vCards;
namespace vCardEditor.View.Customs
{
public partial class AddAddressDialog : Form
{
public List<vCardDeliveryAddressTypes> Addresses { get;}
private readonly List<CheckBox> _checkBoxes;
public AddAddressDialog()
{
InitializeComponent();
_checkBoxes = Controls.OfType<CheckBox>().ToList();
Addresses = new List<vCardDeliveryAddressTypes>();
}
public AddAddressDialog(List<vCardDeliveryAddressTypes> addressCollection)
{
InitializeComponent();
Addresses = addressCollection;
_checkBoxes = Controls.OfType<CheckBox>().ToList();
foreach (var item in addressCollection)
{
switch (item.ToString())
{
case "Home":
cbHome.Checked = true;
break;
case "Work":
cbWork.Checked = true;
break;
case "Postal":
cbPostal.Checked = true;
break;
case "Domestic":
cbDomestic.Checked = true;
break;
case "International":
cbInternational.Checked = true;
break;
case "Default":
cbCustom.Checked = true;
break;
}
}
}
private void btnOK_Click(object sender, EventArgs e)
{
var total = _checkBoxes
.Where(checkBox => checkBox.Checked);
if (total.Count() == 0)
{
MessageBox.Show("One item must be checked!");
DialogResult = DialogResult.None;
return;
}
foreach (var item in total)
{
var enumType = (vCardDeliveryAddressTypes)Enum.Parse(typeof(vCardDeliveryAddressTypes), item.Text, true);
Addresses.Add(enumType);
}
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,252 @@

namespace vCardEditor.View.Customs
{
partial class AddressBox
{
/// <summary>
/// Variable nécessaire au concepteur.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
/// <param name="disposing">true si les ressources managées doivent être supprimées ; sinon, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Code généré par le Concepteur de composants
/// <summary>
/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
/// le contenu de cette méthode avec l'éditeur de code.
/// </summary>
private void InitializeComponent()
{
this.ExtAddrValue = new vCardEditor.View.StateTextBox();
this.ExtAdressLabel = new System.Windows.Forms.Label();
this.StreetLabel = new System.Windows.Forms.Label();
this.StreetValue = new vCardEditor.View.StateTextBox();
this.POBoxLabel = new System.Windows.Forms.Label();
this.CountryValue = new vCardEditor.View.StateTextBox();
this.Country = new System.Windows.Forms.Label();
this.POBoxValue = new vCardEditor.View.StateTextBox();
this.CityLabel = new System.Windows.Forms.Label();
this.RegionValue = new vCardEditor.View.StateTextBox();
this.CityValue = new vCardEditor.View.StateTextBox();
this.StateLabel = new System.Windows.Forms.Label();
this.ZipLabel = new System.Windows.Forms.Label();
this.ZipValue = new vCardEditor.View.StateTextBox();
this.SuspendLayout();
//
// ExtAddrValue
//
this.ExtAddrValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ExtAddrValue.Location = new System.Drawing.Point(90, 45);
this.ExtAddrValue.Margin = new System.Windows.Forms.Padding(4);
this.ExtAddrValue.Name = "ExtAddrValue";
this.ExtAddrValue.oldText = null;
this.ExtAddrValue.Size = new System.Drawing.Size(237, 22);
this.ExtAddrValue.TabIndex = 27;
this.ExtAddrValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.ExtAddrValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// ExtAdressLabel
//
this.ExtAdressLabel.Location = new System.Drawing.Point(1, 42);
this.ExtAdressLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.ExtAdressLabel.Name = "ExtAdressLabel";
this.ExtAdressLabel.Size = new System.Drawing.Size(87, 23);
this.ExtAdressLabel.TabIndex = 26;
this.ExtAdressLabel.Text = "Ext Address:";
this.ExtAdressLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// StreetLabel
//
this.StreetLabel.Location = new System.Drawing.Point(2, 14);
this.StreetLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.StreetLabel.Name = "StreetLabel";
this.StreetLabel.Size = new System.Drawing.Size(65, 23);
this.StreetLabel.TabIndex = 14;
this.StreetLabel.Text = "Address:";
this.StreetLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// StreetValue
//
this.StreetValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.StreetValue.Location = new System.Drawing.Point(90, 14);
this.StreetValue.Margin = new System.Windows.Forms.Padding(4);
this.StreetValue.Name = "StreetValue";
this.StreetValue.oldText = "";
this.StreetValue.Size = new System.Drawing.Size(613, 22);
this.StreetValue.TabIndex = 15;
this.StreetValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.StreetValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// POBoxLabel
//
this.POBoxLabel.Location = new System.Drawing.Point(334, 75);
this.POBoxLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.POBoxLabel.Name = "POBoxLabel";
this.POBoxLabel.Size = new System.Drawing.Size(59, 23);
this.POBoxLabel.TabIndex = 16;
this.POBoxLabel.Text = "PO Box:";
this.POBoxLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// CountryValue
//
this.CountryValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CountryValue.Location = new System.Drawing.Point(579, 76);
this.CountryValue.Margin = new System.Windows.Forms.Padding(4);
this.CountryValue.Name = "CountryValue";
this.CountryValue.oldText = null;
this.CountryValue.Size = new System.Drawing.Size(125, 22);
this.CountryValue.TabIndex = 25;
this.CountryValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.CountryValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// Country
//
this.Country.Location = new System.Drawing.Point(505, 76);
this.Country.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.Country.Name = "Country";
this.Country.Size = new System.Drawing.Size(65, 23);
this.Country.TabIndex = 24;
this.Country.Text = "Country:";
this.Country.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// POBoxValue
//
this.POBoxValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.POBoxValue.Location = new System.Drawing.Point(397, 75);
this.POBoxValue.Margin = new System.Windows.Forms.Padding(4);
this.POBoxValue.Name = "POBoxValue";
this.POBoxValue.oldText = null;
this.POBoxValue.Size = new System.Drawing.Size(100, 22);
this.POBoxValue.TabIndex = 17;
this.POBoxValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.POBoxValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// CityLabel
//
this.CityLabel.Location = new System.Drawing.Point(338, 45);
this.CityLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.CityLabel.Name = "CityLabel";
this.CityLabel.Size = new System.Drawing.Size(32, 23);
this.CityLabel.TabIndex = 18;
this.CityLabel.Text = "City:";
this.CityLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// RegionValue
//
this.RegionValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.RegionValue.Location = new System.Drawing.Point(90, 75);
this.RegionValue.Margin = new System.Windows.Forms.Padding(4);
this.RegionValue.Name = "RegionValue";
this.RegionValue.oldText = null;
this.RegionValue.Size = new System.Drawing.Size(236, 22);
this.RegionValue.TabIndex = 23;
this.RegionValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.RegionValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// CityValue
//
this.CityValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CityValue.Location = new System.Drawing.Point(397, 45);
this.CityValue.Margin = new System.Windows.Forms.Padding(4);
this.CityValue.Name = "CityValue";
this.CityValue.oldText = null;
this.CityValue.Size = new System.Drawing.Size(127, 22);
this.CityValue.TabIndex = 19;
this.CityValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.CityValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// StateLabel
//
this.StateLabel.Location = new System.Drawing.Point(17, 74);
this.StateLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.StateLabel.Name = "StateLabel";
this.StateLabel.Size = new System.Drawing.Size(61, 23);
this.StateLabel.TabIndex = 22;
this.StateLabel.Text = "Region:";
this.StateLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// ZipLabel
//
this.ZipLabel.Location = new System.Drawing.Point(533, 45);
this.ZipLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.ZipLabel.Name = "ZipLabel";
this.ZipLabel.Size = new System.Drawing.Size(37, 23);
this.ZipLabel.TabIndex = 20;
this.ZipLabel.Text = "Zip:";
this.ZipLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// ZipValue
//
this.ZipValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ZipValue.Location = new System.Drawing.Point(579, 46);
this.ZipValue.Margin = new System.Windows.Forms.Padding(4);
this.ZipValue.Name = "ZipValue";
this.ZipValue.oldText = null;
this.ZipValue.Size = new System.Drawing.Size(124, 22);
this.ZipValue.TabIndex = 21;
this.ZipValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.ZipValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// AddressBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.ExtAddrValue);
this.Controls.Add(this.ExtAdressLabel);
this.Controls.Add(this.StreetLabel);
this.Controls.Add(this.StreetValue);
this.Controls.Add(this.POBoxLabel);
this.Controls.Add(this.CountryValue);
this.Controls.Add(this.Country);
this.Controls.Add(this.POBoxValue);
this.Controls.Add(this.CityLabel);
this.Controls.Add(this.RegionValue);
this.Controls.Add(this.CityValue);
this.Controls.Add(this.StateLabel);
this.Controls.Add(this.ZipLabel);
this.Controls.Add(this.ZipValue);
this.Name = "AddressBox";
this.Size = new System.Drawing.Size(706, 104);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
internal StateTextBox ExtAddrValue;
internal System.Windows.Forms.Label ExtAdressLabel;
internal System.Windows.Forms.Label StreetLabel;
internal StateTextBox StreetValue;
internal System.Windows.Forms.Label POBoxLabel;
internal StateTextBox CountryValue;
internal System.Windows.Forms.Label Country;
internal StateTextBox POBoxValue;
internal System.Windows.Forms.Label CityLabel;
internal StateTextBox RegionValue;
internal StateTextBox CityValue;
internal System.Windows.Forms.Label StateLabel;
internal System.Windows.Forms.Label ZipLabel;
internal StateTextBox ZipValue;
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Thought.vCards;
namespace vCardEditor.View.Customs
{
public partial class AddressBox : UserControl
{
public event EventHandler TextChangedEvent;
public List<vCardDeliveryAddressTypes> AddressType { get; set; }
public AddressBox(string street, string city, string region, string country, string postalCode,
string extendedAddress, string postOfficeBox, List<vCardDeliveryAddressTypes> addressType)
{
InitializeComponent();
this.AddressType = addressType;
CityValue.Text = city;
CityValue.oldText = city;
CountryValue.Text = country;
CountryValue.oldText = country;
ZipValue.Text = postalCode;
ZipValue.oldText = postalCode;
RegionValue.Text = region;
RegionValue.oldText = region;
StreetValue.Text = street;
StreetValue.oldText = street;
ExtAddrValue.Text = extendedAddress;
ExtAddrValue.oldText = extendedAddress;
POBoxValue.Text = postOfficeBox;
POBoxValue.oldText = postOfficeBox;
}
private void Value_TextChanged(object sender, EventArgs e)
{
TextChangedEvent?.Invoke(sender, e);
}
public vCardDeliveryAddress getDeliveryAddress()
{
var deliveryAddress = new vCardDeliveryAddress
{
City = CityValue.Text,
Country = CountryValue.Text,
PostalCode = ZipValue.Text,
Region = RegionValue.Text,
Street = StreetValue.Text,
ExtendedAddress = ExtAddrValue.Text,
PostOfficeBox = POBoxValue.Text,
AddressType = AddressType
};
return deliveryAddress;
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Thought.vCards;
using VCFEditor.View;
namespace vCardEditor.View.Customs
{
class AddressTabControl : TabControl
{
public event EventHandler TextChangedEvent;
public event EventHandler<EventArg<List<vCardDeliveryAddressTypes>>> AddTab;
public event EventHandler<EventArg<int>> RemoveTab;
public event EventHandler<EventArg<List<vCardDeliveryAddressTypes>>> ModifyTab;
public AddressTabControl()
{
Padding = new Point(20, 20);
ShowToolTips = true;
DrawMode = TabDrawMode.OwnerDrawFixed;
DrawItem += tbcAddress_DrawItem;
MouseDown += tbcAddress_MouseDown;
Selecting += tbcAddress_Selecting;
HandleCreated += tbcAddress_HandleCreated;
MouseDoubleClick += AddressTabControl_MouseDoubleClick;
}
public void getDeliveryAddress(vCard card)
{
if (TabCount < 2)
return;
card.DeliveryAddresses.Clear();
for (int i = 0; i < TabCount - 1; i++)
{
if (TabPages[i].Controls.Count == 0) continue;
AddressBox adr = TabPages[i].Controls[0] as AddressBox;
card.DeliveryAddresses.Add(adr.getDeliveryAddress());
}
}
private void AddressTabControl_MouseDoubleClick(object sender, MouseEventArgs e)
{
TabPage SlectedTab;
for (int i = 0; i < TabPages.Count - 1; ++i)
{
if (GetTabRect(i).Contains(e.Location))
{
var AddressBox = TabPages[i].Controls[0] as AddressBox;
var diag = new AddAddressDialog(AddressBox.AddressType);
if (diag.ShowDialog() == DialogResult.OK)
{
SlectedTab = TabPages[i];
SelectedTab.Text = GetTabTitle(diag.Addresses);
SelectedTab.ToolTipText = string.Join(",", diag.Addresses.ConvertAll(f => f.ToString()));
ModifyTab?.Invoke(sender, new EventArg<List<vCardDeliveryAddressTypes>>(diag.Addresses));
}
break;
}
}
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private const int TCM_SETMINTABWIDTH = 0x1300 + 49;
private void tbcAddress_HandleCreated(object sender, EventArgs e)
{
SendMessage(Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
}
private void tbcAddress_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPageIndex == TabCount - 1)
e.Cancel = true;
}
private void tbcAddress_MouseDown(object sender, MouseEventArgs e)
{
var lastIndex = TabCount - 1;
if (GetTabRect(lastIndex).Contains(e.Location))
{
var diag = new AddAddressDialog();
if (diag.ShowDialog() == DialogResult.OK)
{
vCardDeliveryAddress da = new vCardDeliveryAddress();
da.AddressType = diag.Addresses;
AddtabForAddress(da);
AddTab?.Invoke(sender, new EventArg<List<vCardDeliveryAddressTypes>>(diag.Addresses));
SelectedIndex = TabCount - 1;
}
}
else
{
for (var i = 0; i < TabPages.Count; i++)
{
var tabRect = GetTabRect(i);
tabRect.Inflate(-2, -2);
var closeImage = Properties.Resources.Close;
var imageRect = new Rectangle(
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2,
closeImage.Width, closeImage.Height);
if (imageRect.Contains(e.Location))
{
if (MessageBox.Show("Remove tab?", "Asking", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
TabPages.RemoveAt(i);
SelectedIndex = 0;
RemoveTab?.Invoke(sender, new EventArg<int>(i));
}
return;
}
}
}
}
private void tbcAddress_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index > TabCount - 1)
return;
var tabRect = GetTabRect(e.Index);
tabRect.Inflate(-2, -2);
if (e.Index == TabCount - 1)
{
var addImage = Properties.Resources.Add;
e.Graphics.DrawImage(addImage,
tabRect.Left + (tabRect.Width - addImage.Width) / 2,
tabRect.Top + (tabRect.Height - addImage.Height) / 2);
}
else
{
var closeImage = Properties.Resources.Close;
e.Graphics.DrawImage(closeImage,
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
TabPage SelectedTab = TabPages[e.Index];
Rectangle HeaderRect = GetTabRect(e.Index);
SolidBrush TextBrush = new SolidBrush(Color.Black);
StringFormat sf = new StringFormat
{
LineAlignment = StringAlignment.Center
};
if (e.State == DrawItemState.Selected)
{
Font BoldFont = new Font(Font.Name, Font.Size, FontStyle.Bold);
e.Graphics.DrawString(SelectedTab.Text, BoldFont, TextBrush, HeaderRect, sf);
}
else
e.Graphics.DrawString(SelectedTab.Text , e.Font, TextBrush, HeaderRect, sf);
TextBrush.Dispose();
}
}
public void SetAddresses(vCard card)
{
ClearTabs();
AddTabForEveryAddress(card);
}
private void AddTabForEveryAddress(vCard card)
{
foreach (var item in card.DeliveryAddresses)
AddtabForAddress(item);
SelectedIndex = 0;
}
private void AddtabForAddress(vCardDeliveryAddress da)
{
string title = GetTabTitle(da.AddressType);
var page = new TabPage($" {title} ");
TabPages.Insert(TabCount - 1, page);
var ab = new AddressBox(da.Street, da.City, da.Region, da.Country,
da.PostalCode, da.ExtendedAddress, da.PostOfficeBox, da.AddressType);
ab.TextChangedEvent += (s, e) => TextChangedEvent?.Invoke(s, e);
page.Controls.Add(ab);
page.ToolTipText = string.Join(",", da.AddressType.ConvertAll(f => f.ToString()));
}
private string GetTabTitle(List<vCardDeliveryAddressTypes> addressTypes)
{
var title = string.Empty;
if (addressTypes.Count > 0)
{
title = addressTypes[0].ToString();
if (addressTypes.Count > 1)
title += "...";
}
return title;
}
private void ClearTabs()
{
//Remove every tab (except "+"). We don't call Clear() as it doesn't free memory.
while (TabCount > 1)
TabPages[0].Dispose();
}
}
}

View File

@@ -0,0 +1,119 @@

namespace vCardEditor.View.Customs
{
partial class ColumnsDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.cbFamilyName = new System.Windows.Forms.CheckBox();
this.cbCellular = new System.Windows.Forms.CheckBox();
this.cbName = new System.Windows.Forms.CheckBox();
this.btnCancel = new System.Windows.Forms.Button();
this.btnOK = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// cbFamilyName
//
this.cbFamilyName.AutoSize = true;
this.cbFamilyName.Location = new System.Drawing.Point(12, 39);
this.cbFamilyName.Name = "cbFamilyName";
this.cbFamilyName.Size = new System.Drawing.Size(107, 21);
this.cbFamilyName.TabIndex = 5;
this.cbFamilyName.Text = "FamilyName";
this.cbFamilyName.UseVisualStyleBackColor = true;
//
// cbCellular
//
this.cbCellular.AutoSize = true;
this.cbCellular.Location = new System.Drawing.Point(12, 66);
this.cbCellular.Name = "cbCellular";
this.cbCellular.Size = new System.Drawing.Size(77, 21);
this.cbCellular.TabIndex = 4;
this.cbCellular.Text = "Cellular";
this.cbCellular.UseVisualStyleBackColor = true;
//
// cbName
//
this.cbName.AutoSize = true;
this.cbName.Checked = true;
this.cbName.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbName.Enabled = false;
this.cbName.Location = new System.Drawing.Point(12, 12);
this.cbName.Name = "cbName";
this.cbName.Size = new System.Drawing.Size(67, 21);
this.cbName.TabIndex = 3;
this.cbName.Text = "Name";
this.cbName.UseVisualStyleBackColor = true;
//
// btnCancel
//
this.btnCancel.CausesValidation = false;
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(190, 119);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 10;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// btnOK
//
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.Location = new System.Drawing.Point(109, 119);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(75, 23);
this.btnOK.TabIndex = 9;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// ColumnsDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(277, 149);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.cbFamilyName);
this.Controls.Add(this.cbCellular);
this.Controls.Add(this.cbName);
this.Name = "ColumnsDialog";
this.Text = "Columns...";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.CheckBox cbFamilyName;
private System.Windows.Forms.CheckBox cbCellular;
private System.Windows.Forms.CheckBox cbName;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Button btnOK;
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using vCardEditor.Model;
namespace vCardEditor.View.Customs
{
public partial class ColumnsDialog : Form
{
private readonly List<CheckBox> _checkBoxes;
public List<Column> Columns { get; }
public ColumnsDialog(List<Column> columns)
{
InitializeComponent();
_checkBoxes = Controls.OfType<CheckBox>().ToList();
Columns = columns;
foreach (var item in columns)
{
switch (item)
{
case Model.Column.FamilyName:
cbFamilyName.Checked = true;
break;
case Model.Column.Cellular:
cbCellular.Checked = true;
break;
}
}
}
private void btnOK_Click(object sender, EventArgs e)
{
Columns.Clear();
var total = _checkBoxes
.Where(checkBox => checkBox.Checked);
foreach (var item in total)
{
var enumType = (Column)Enum.Parse(typeof(Column), item.Text, true);
Columns.Add(enumType);
}
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -2,15 +2,14 @@
using System.Collections.Generic;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using System.Windows.Forms;
using vCardEditor.Model;
using vCardEditor.View;
namespace VCFEditor.View
{
public interface IMainView
{
#region All events
event EventHandler<EventArg<FormState>> LoadForm;
event EventHandler AddContact;
event EventHandler DeleteContact;
event EventHandler BeforeOpeningNewFile;
@@ -21,14 +20,25 @@ namespace VCFEditor.View
event EventHandler<EventArg<string>> FilterTextChanged;
event EventHandler TextBoxValueChanged;
event EventHandler<EventArg<bool>> CloseForm;
#endregion
event EventHandler<EventArg<string>> ModifyImage;
event EventHandler ExportImage;
event EventHandler<EventArg<List<vCardDeliveryAddressTypes>>> AddressAdded;
event EventHandler<EventArg<List<vCardDeliveryAddressTypes>>> AddressModified;
event EventHandler<EventArg<int>> AddressRemoved;
event EventHandler CopyTextToClipboardEvent;
int SelectedContactIndex { get; }
void DisplayContacts(BindingList<Contact> contacts);
void DisplayContacts(SortableBindingList<Contact> contacts);
void DisplayContactDetail(vCard card, string FileName);
void ClearContactDetail();
bool AskMessage(string msg, string caption);
void DisplayMessage(string msg, string caption);
string DisplayOpenDialog();
string DisplayOpenDialog(string filter);
string DisplaySaveDialog(string filename);
void UpdateMRUMenu(FixedList MRUList);
void SendTextToClipBoard(string text);
FormState GetFormState();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,15 @@ using VCFEditor.Model;
using Thought.vCards;
using vCardEditor.Repository;
using vCardEditor.Model;
using System.Drawing;
using System.Collections.Generic;
using vCardEditor.View.Customs;
namespace vCardEditor.View
{
public partial class MainForm : Form, IMainView
{
#region event list
public event EventHandler<EventArg<FormState>> LoadForm;
public event EventHandler AddContact;
public event EventHandler SaveContactsSelected;
public event EventHandler BeforeOpeningNewFile;
@@ -23,9 +26,16 @@ namespace vCardEditor.View
public event EventHandler<EventArg<string>> FilterTextChanged;
public event EventHandler TextBoxValueChanged;
public event EventHandler<EventArg<bool>> CloseForm;
#endregion
public event EventHandler<EventArg<string>> ModifyImage;
public event EventHandler<EventArg<List<vCardDeliveryAddressTypes>>> AddressAdded;
public event EventHandler<EventArg<List<vCardDeliveryAddressTypes>>> AddressModified;
public event EventHandler<EventArg<int>> AddressRemoved;
public event EventHandler ExportImage;
public event EventHandler CopyTextToClipboardEvent;
ComponentResourceManager resources;
public int SelectedContactIndex
{
get
@@ -42,23 +52,22 @@ namespace vCardEditor.View
{
InitializeComponent();
resources = new ComponentResourceManager(typeof(MainForm));
tbcAddress.AddTab += (sender, e) => AddressAdded?.Invoke(sender, e);
tbcAddress.RemoveTab += (sender, e) => AddressRemoved?.Invoke(sender, e);
tbcAddress.ModifyTab += (sender, e) => AddressModified?.Invoke(sender, e);
tbcAddress.TextChangedEvent += (sender, e) => TextBoxValueChanged?.Invoke(sender, e);
BuildMRUMenu();
}
private void tbsOpen_Click(object sender, EventArgs e)
{
if (NewFileOpened != null)
NewFileOpened(sender, new EventArg<string>(string.Empty));
NewFileOpened?.Invoke(sender, new EventArg<string>(string.Empty));
}
public void DisplayContacts(BindingList<Contact> contacts)
public void DisplayContacts(SortableBindingList<Contact> contacts)
{
if (contacts != null)
this.bsContacts.DataSource = contacts;
bsContacts.DataSource = contacts;
}
@@ -67,7 +76,7 @@ namespace vCardEditor.View
if (SaveContactsSelected != null)
{
//make sure the last changes in the textboxes is saved.
this.Validate();
Validate();
SaveContactsSelected(sender, e);
}
@@ -75,24 +84,23 @@ namespace vCardEditor.View
private void tbsNew_Click(object sender, EventArgs e)
{
if (AddContact != null)
{
AddContact(sender, e);
}
AddContact?.Invoke(sender, e);
}
private void dgContacts_SelectionChanged(object sender, EventArgs e)
{
if (ChangeContactsSelected != null && dgContacts.CurrentCell != null)
ChangeContactsSelected(sender, new EventArg<vCard>(getvCard()));
{
vCard data = GetvCardFromWindow();
ChangeContactsSelected(sender, new EventArg<vCard>(data));
}
else
ChangeContactsSelected(sender, new EventArg<vCard>(null));
}
private void Value_TextChanged(object sender, EventArgs e)
{
if (TextBoxValueChanged != null)
TextBoxValueChanged(sender, e);
TextBoxValueChanged?.Invoke(sender, e);
}
public void DisplayContactDetail(vCard card, string FileName)
@@ -100,7 +108,7 @@ namespace vCardEditor.View
if (card == null)
throw new ArgumentException("card must be valid!");
this.Text = string.Format("{0} - vCard Editor", FileName);
Text = string.Format("{0} - vCard Editor", FileName);
gbContactDetail.Enabled = true;
gbNameList.Enabled = true;
@@ -114,13 +122,31 @@ namespace vCardEditor.View
SetSummaryValue(WorkPhoneValue, card.Phones.GetFirstChoice(vCardPhoneTypes.Work));
SetSummaryValue(EmailAddressValue, card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet));
SetSummaryValue(PersonalWebSiteValue, card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal));
SetAddressesValues(card.DeliveryAddresses);
SetAddressesValues(card);
SetPhotoValue(card.Photos);
}
#region helper methods to populate textboxes.
public void ClearContactDetail()
{
gbContactDetail.Enabled = false;
gbNameList.Enabled = false;
SetSummaryValue(firstNameValue, string.Empty);
SetSummaryValue(lastNameValue, string.Empty);
SetSummaryValue(middleNameValue, string.Empty);
SetSummaryValue(FormattedTitleValue, string.Empty);
SetSummaryValue(FormattedNameValue, string.Empty);
SetSummaryValue(HomePhoneValue, string.Empty);
SetSummaryValue(CellularPhoneValue, string.Empty);
SetSummaryValue(WorkPhoneValue, string.Empty);
SetSummaryValue(EmailAddressValue, string.Empty);
SetSummaryValue(PersonalWebSiteValue, string.Empty);
SetAddressesValues(new vCard());
SetPhotoValue(new vCardPhotoCollection());
}
private void SetSummaryValue(StateTextBox valueLabel, string value)
{
if (valueLabel == null)
@@ -160,8 +186,7 @@ namespace vCardEditor.View
var photo = photos[0];
try
{
// Get the bytes of the photo if it has
// not already been loaded.
// Get the bytes of the photo if it has not already been loaded.
if (!photo.IsLoaded)
photo.Fetch();
@@ -170,78 +195,18 @@ namespace vCardEditor.View
catch
{
//Empty image icon instead.
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
PhotoBox.Image = (Image)resources.GetObject("PhotoBox.Image");
}
}
else
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
PhotoBox.Image = (Image)resources.GetObject("PhotoBox.Image");
}
private void SetAddressesValues(vCardDeliveryAddressCollection addresses)
private void SetAddressesValues(vCard card)
{
ClearAddressTextFields();
if (addresses.Any())
{
var HomeAddress = addresses.Where(x => x.IsHome).FirstOrDefault();
if (HomeAddress != null)
{
HomeAddressValue.Text = HomeAddress.Street;
HomeCityValue.Text = HomeAddress.City;
HomeZipValue.Text = HomeAddress.PostalCode;
HomeStateValue.Text = HomeAddress.Region;
HomeCountryValue.Text = HomeAddress.Country;
}
var WorkAddress = addresses.Where(x => x.IsWork).FirstOrDefault();
if (WorkAddress != null)
{
WorkAddressValue.Text = WorkAddress.Street;
WorkCityValue.Text = WorkAddress.City;
WorkZipValue.Text = WorkAddress.PostalCode;
WorkStateValue.Text = WorkAddress.Region;
WorkCountryValue.Text = WorkAddress.Country;
}
var PostalAddress = addresses.Where(x => x.IsPostal).FirstOrDefault();
if (PostalAddress != null)
{
PostalAddressValue.Text = PostalAddress.Street;
PostalAddressValue.Text = PostalAddress.Street;
PostalCityValue.Text = PostalAddress.City;
PostalZipValue.Text = PostalAddress.PostalCode;
PostalStateValue.Text = PostalAddress.Region;
PostalCountryValue.Text = PostalAddress.Country;
}
}
tbcAddress.SetAddresses(card);
}
private void ClearAddressTextFields()
{
HomeAddressValue.Clear();
HomePOBoxValue.Clear();
HomeCityValue.Clear();
HomeZipValue.Clear();
HomeStateValue.Clear();
HomeCountryValue.Clear();
WorkAddressValue.Clear();
WorkPOBoxValue.Clear();
WorkCityValue.Clear();
WorkZipValue.Clear();
WorkStateValue.Clear();
WorkCountryValue.Clear();
PostalAddressValue.Clear();
PostalPOBoxValue.Clear();
PostalCityValue.Clear();
PostalZipValue.Clear();
PostalStateValue.Clear();
PostalCountryValue.Clear();
}
#endregion
private void tbsDelete_Click(object sender, EventArgs e)
{
if (DeleteContact != null)
@@ -255,19 +220,15 @@ namespace vCardEditor.View
private void tbsAbout_Click(object sender, EventArgs e)
{
AboutDialog dialog = new AboutDialog();
dialog.ShowDialog();
new AboutDialog().ShowDialog();
}
private void textBoxFilter_TextChanged(object sender, EventArgs e)
{
//Save before leaving contact.
if (BeforeLeavingContact != null)
BeforeLeavingContact(sender, new EventArg<vCard>(getvCard()));
BeforeLeavingContact?.Invoke(sender, new EventArg<vCard>(GetvCardFromWindow()));
//filter.
if (FilterTextChanged != null)
FilterTextChanged(sender, new EventArg<string>(textBoxFilter.Text));
FilterTextChanged?.Invoke(sender, new EventArg<string>(textBoxFilter.Text));
}
private void btnClearFilter_Click(object sender, EventArgs e)
@@ -275,15 +236,12 @@ namespace vCardEditor.View
textBoxFilter.Text = string.Empty;
}
/// <summary>
/// Generate a vcard from differents fields
/// </summary>
/// <returns></returns>
private vCard getvCard()
private vCard GetvCardFromWindow()
{
vCard card = new vCard
{
Title = FormattedTitleValue.Text,
FormattedName = FormattedNameValue.Text,
GivenName = firstNameValue.Text,
@@ -298,46 +256,29 @@ namespace vCardEditor.View
card.Phones.Add(new vCardPhone(CellularPhoneValue.Text, vCardPhoneTypes.Cellular));
if (!string.IsNullOrEmpty(WorkPhoneValue.Text))
card.Phones.Add(new vCardPhone(WorkPhoneValue.Text, vCardPhoneTypes.Work));
if (!string.IsNullOrEmpty(this.EmailAddressValue.Text))
card.EmailAddresses.Add(new vCardEmailAddress(this.EmailAddressValue.Text));
if (!string.IsNullOrEmpty(this.PersonalWebSiteValue.Text))
card.Websites.Add(new vCardWebsite(this.PersonalWebSiteValue.Text));
if (!string.IsNullOrEmpty(this.HomeAddressValue.Text))
card.DeliveryAddresses.Add(new vCardDeliveryAddress(HomeAddressValue.Text, HomeCityValue.Text, HomeStateValue.Text, HomeCountryValue.Text,
HomePOBoxValue.Text, vCardDeliveryAddressTypes.Home));
if (!string.IsNullOrEmpty(this.WorkAddressValue.Text))
card.DeliveryAddresses.Add(new vCardDeliveryAddress(WorkAddressValue.Text, WorkCityValue.Text, WorkStateValue.Text, WorkCountryValue.Text,
WorkPOBoxValue.Text, vCardDeliveryAddressTypes.Work));
if (!string.IsNullOrEmpty(this.PostalAddressValue.Text))
card.DeliveryAddresses.Add(new vCardDeliveryAddress(PostalAddressValue.Text, PostalCityValue.Text, PostalStateValue.Text, PostalCountryValue.Text,
PostalPOBoxValue.Text, vCardDeliveryAddressTypes.Postal));
tbcAddress.getDeliveryAddress(card);
return card;
}
private void dgContacts_RowLeave(object sender, DataGridViewCellEventArgs e)
{
if (BeforeLeavingContact != null)
BeforeLeavingContact(sender, new EventArg<vCard>(getvCard()));
vCard data = GetvCardFromWindow();
BeforeLeavingContact?.Invoke(sender, new EventArg<vCard>(data));
}
private void miQuit_Click(object sender, EventArgs e)
{
this.Close();
Close();
}
#region drag&drop
/// <summary>
/// Make our form accept drag&drop
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainForm_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
@@ -352,43 +293,40 @@ namespace vCardEditor.View
return;
}
NewFileOpened(sender, new EventArg<string>(FileList[0]));
}
#endregion
private void BuildMRUMenu()
{
recentFilesMenuItem.DropDownItemClicked += (s, e) => NewFileOpened(s, new EventArg<string>(e.ClickedItem.Text));
//Update the MRU Menu entries..
recentFilesMenuItem.DropDownItemClicked += (s, e) =>
{
var evt = new EventArg<string>(e.ClickedItem.Text);
NewFileOpened(s, evt);
};
UpdateMRUMenu(ConfigRepository.Instance.Paths);
}
public void UpdateMRUMenu(FixedList MRUList)
public void UpdateMRUMenu(FixedList MostRecentFilesList)
{
//No need to go further if no menu entry to load!
if (MRUList == null || MRUList.IsEmpty())
if (MostRecentFilesList == null || MostRecentFilesList.IsEmpty())
return;
recentFilesMenuItem.DropDownItems.Clear();
for (int i = 0; i < MRUList._innerList.Count; i++)
recentFilesMenuItem.DropDownItems.Add(MRUList[i]);
for (int i = 0; i < MostRecentFilesList._innerList.Count; i++)
recentFilesMenuItem.DropDownItems.Add(MostRecentFilesList[i]);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
var evt = new EventArg<bool>(false);
if (CloseForm != null)
CloseForm(sender,evt);
CloseForm?.Invoke(sender, evt);
e.Cancel = evt.Data;
ConfigRepository.Instance.SaveConfig();
}
public bool AskMessage(string msg, string caption)
@@ -403,24 +341,19 @@ namespace vCardEditor.View
return result;
}
/// <summary>
/// Load the config dialog
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void miConfig_Click(object sender, EventArgs e)
{
ConfigDialog dialog = new ConfigDialog();
dialog.ShowDialog();
new ConfigDialog().ShowDialog();
}
public void DisplayMessage(string msg, string caption)
{
MessageBox.Show(msg, caption);
}
public string DisplayOpenDialog()
public string DisplayOpenDialog(string filter = "")
{
string filename = string.Empty;
openFileDialog.Filter = filter;
DialogResult result = openFileDialog.ShowDialog();
if (result == DialogResult.OK)
@@ -429,8 +362,160 @@ namespace vCardEditor.View
return filename;
}
public string DisplaySaveDialog(string filename)
{
var saveFileDialog = new SaveFileDialog();
saveFileDialog.FileName = filename;
DialogResult result = saveFileDialog.ShowDialog();
if (result == DialogResult.OK)
filename = saveFileDialog.FileName;
return filename;
}
private void PhotoBox_Click(object sender, EventArgs e)
{
if (ModifyImage != null)
{
var fileName = DisplayOpenDialog();
if (!string.IsNullOrEmpty(fileName))
{
try
{
PhotoBox.Image = new Bitmap(fileName);
var evt = new EventArg<string>(fileName);
ModifyImage(sender, evt);
}
catch (ArgumentException)
{
MessageBox.Show($"Invalid file! : {fileName}");
}
}
}
}
private void btnRemoveImage_Click(object sender, EventArgs e)
{
PhotoBox.Image = (Image)resources.GetObject("PhotoBox.Image");
//Remove image from vcf
ModifyImage(sender, new EventArg<string>(""));
}
private void btnExportImage_Click(object sender, EventArgs e)
{
ExportImage?.Invoke(sender, e);
}
private void copyToolStripMenuItem_Click(object sender, EventArgs e)
{
CopyTextToClipboardEvent?.Invoke(sender, e);
}
public void SendTextToClipBoard(string text)
{
Clipboard.SetText(text);
}
private void dgContacts_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
{
if (e.RowIndex == -1)
{
e.ContextMenuStrip = contextMenuStrip1;
}
}
private void modifiyColumnsToolStripMenuItem_Click(object sender, EventArgs e)
{
List<Column> Columns = GetListColumnsForDataGrid();
var dialog = new ColumnsDialog(Columns);
if (dialog.ShowDialog() == DialogResult.OK)
{
ToggleAllColumnsToInvisible();
ToggleOnlySelected(dialog.Columns);
}
}
private List<Column> GetListColumnsForDataGrid()
{
List<Column> Columns = new List<Column>();
for (int i = 2; i < dgContacts.Columns.Count; i++)
{
if (dgContacts.Columns[i].Visible)
{
var name = dgContacts.Columns[i].Name;
var enumType = (Column)Enum.Parse(typeof(Column), name, true);
Columns.Add(enumType);
}
}
return Columns;
}
private void ToggleOnlySelected(List<Column> columns)
{
foreach (var item in columns)
{
switch (item)
{
case Column.FamilyName:
dgContacts.Columns["FamilyName"].Visible = true;
break;
case Column.Cellular:
dgContacts.Columns["Cellular"].Visible = true;
break;
}
}
}
private void ToggleAllColumnsToInvisible()
{
for (int i = 2; i < dgContacts.Columns.Count; i++)
{
dgContacts.Columns[i].Visible = false;
}
}
public FormState GetFormState()
{
return new FormState
{
Columns = GetListColumnsForDataGrid(),
X = Location.X,
Y = Location.Y,
Height = Size.Height,
Width = Size.Width,
splitterPosition = splitContainer1.SplitterDistance
};
}
private void MainForm_Load(object sender, EventArgs e)
{
var evt = new EventArg<FormState>(new FormState());
LoadForm?.Invoke(sender, evt);
//TODO: Better way to check if state was serialised!
var state = evt.Data;
if (state.Width != 0 && state.Height != 0)
{
Size = new Size(state.Width, state.Height);
Location = new Point(state.X , state.Y);
splitContainer1.SplitterDistance = state.splitterPosition;
if (state.Columns != null)
{
ToggleOnlySelected(state.Columns);
}
}
}
}
}

View File

@@ -252,6 +252,28 @@
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>353, 17</value>
</metadata>
<data name="btnExportImage.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL
EwAACxMBAJqcGAAAAZFJREFUOE/NkMtKAlEAhn2Ctq26qmPavTdp3b4Iih6gnqMyoqCw0hIru5hJmFlI
FBE0pNXo2IzO1YNZGK3+xtOIC81t/fBvDnzf+c+x/J+MREi690BHx5qA4ts7bYEUIas6VmMsEiyHpctn
OHeVqO1IbzGxWoZPCVzBH4GmE6hGK7CYV9A654c7cofFiyf07KpgAnLUxGoZChM49zUqyEkKrZCTwb/m
qGAhfIv5WBKOgALGr8DEahk8KcBVEayLuHwUkM6K4DICnjiewmc3D5gNPVKY2ZHrBQOhAvqPdDrR4c+D
8YmwV+oVYNsSYDXK+IxzA7ZvNxD0H+voOzR6oKE3qNE1zj31R2jOrsI2n1QvqMJj8SJmrouYThBMXRUw
GVcxca5gPCpjNCRR2OptJDBv/vj8QrlcRqlUAiEEmqZBkiSIooiXDE/h7q18vaA6+zeY53lwHEfhro0G
guqbm8GpVIrCnZ5cvaDy28xmtinMsizaVjJoX+YaCDx81u5J4174HQ7fsBRucyezJvbnsVi+AVtEwzA2
nUJSAAAAAElFTkSuQmCC
</value>
</data>
<data name="btnRemoveImage.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL
EwAACxMBAJqcGAAAAJdJREFUOE9jGFzgv7Ex6397exYoFwOA5EBqoFxU8D80lPmLs+lyIF6NTRFY3sls
CRCvxWoIXIGz2X90QzDkcLkSmyFEa4YBFA1OpmuAeBnRmmEAashSiEaIQURrBgGIAebkGYDqBTOgF2Au
IdX/UA3YxKDKUQE+hUQZAlbkDApx7ArghuBKSCAAjndcTgQCkBxOzQMEGBgA54+vl3zobyEAAAAASUVO
RK5CYII=
</value>
</data>
<data name="PhotoBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAAABGdBTUEAALGPC/xhBQAAAIdQTFRF////
@@ -282,6 +304,18 @@
<metadata name="bsContacts.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>486, 17</value>
</metadata>
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="FormattedName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="FamilyName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Cellular.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="btnClearFilter.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@@ -299,11 +333,8 @@
TkSuQmCC
</value>
</data>
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>618, 17</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using vCardEditor.Model;
namespace vCardEditor.View
{
public class SortableBindingList<T> : BindingList<T>
{
private readonly Dictionary<Type, PropertyComparer<T>> comparers;
private bool isSorted;
private ListSortDirection listSortDirection;
private PropertyDescriptor propertyDescriptor;
public SortableBindingList()
: base(new List<T>())
{
this.comparers = new Dictionary<Type, PropertyComparer<T>>();
}
public SortableBindingList(IEnumerable<T> enumeration)
: base(new List<T>(enumeration))
{
this.comparers = new Dictionary<Type, PropertyComparer<T>>();
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override bool IsSortedCore
{
get { return this.isSorted; }
}
protected override PropertyDescriptor SortPropertyCore
{
get { return this.propertyDescriptor; }
}
protected override ListSortDirection SortDirectionCore
{
get { return this.listSortDirection; }
}
protected override bool SupportsSearchingCore
{
get { return true; }
}
protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
{
List<T> itemsList = (List<T>)this.Items;
Type propertyType = property.PropertyType;
PropertyComparer<T> comparer;
if (!this.comparers.TryGetValue(propertyType, out comparer))
{
comparer = new PropertyComparer<T>(property, direction);
this.comparers.Add(propertyType, comparer);
}
comparer.SetPropertyAndDirection(property, direction);
itemsList.Sort(comparer);
this.propertyDescriptor = property;
this.listSortDirection = direction;
this.isSorted = true;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
protected override void RemoveSortCore()
{
this.isSorted = false;
this.propertyDescriptor = base.SortPropertyCore;
this.listSortDirection = base.SortDirectionCore;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
protected override int FindCore(PropertyDescriptor property, object key)
{
int count = this.Count;
for (int i = 0; i < count; ++i)
{
T element = this[i];
if (property.GetValue(element).Equals(key))
{
return i;
}
}
return -1;
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace UIToolbox
{
/// <summary>
/// Summary description for CollapseBox.
/// </summary>
public class CollapseBox : OwnerDrawButton
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
#region Internal variables
private bool m_bIsPlus;
#endregion Internal variables
public CollapseBox()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// CollapseBox
//
this.Click += new System.EventHandler(this.CollapseBox_Click);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.CollapseBox_Paint);
this.DoubleClick += new System.EventHandler(this.CollapseBox_DoubleClick);
}
#endregion
#region Events
private void CollapseBox_Click(object sender, System.EventArgs e)
{
IsPlus = !IsPlus;
}
private void CollapseBox_DoubleClick(object sender, System.EventArgs e)
{
// fast clicking registers as double-clicking, so map a double-click
// event into a single click.
CollapseBox_Click(sender, e);
}
private void CollapseBox_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
if(m_ButtonState == ButtonState.TrackingInside)
g.FillRectangle(Brushes.LightGray, ClientRectangle);
else
g.FillRectangle(Brushes.White, ClientRectangle);
Rectangle theRec = new Rectangle();
theRec = ClientRectangle;
theRec.Width--;
theRec.Height--;
g.DrawRectangle(Pens.Black, theRec);
g.DrawLine(Pens.Black, theRec.X + 2, theRec.Y + (this.Height/2),
theRec.X + this.Width - 3, theRec.Y + (this.Height/2));
if(m_bIsPlus)
{
g.DrawLine(Pens.Black, theRec.X + (this.Width/2), theRec.Y + 2,
theRec.X + (this.Width/2), theRec.Y + this.Height - 3);
}
}
#endregion Events
#region Accessors
[DefaultValue(false)]
public bool IsPlus
{
get
{
return m_bIsPlus;
}
set
{
if(m_bIsPlus != value)
{
m_bIsPlus = value;
Invalidate();
}
}
}
#endregion Accessors
}
}

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Name">
<value>CollapseBox</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

View File

@@ -0,0 +1,326 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace UIToolbox
{
/// <summary>
/// Summary description for CollapsibleGroupBox.
/// </summary>
public class CollapsibleGroupBox : System.Windows.Forms.UserControl
{
public const int kCollapsedHeight = 20;
#region Members
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private CollapseBox m_CollapseBox;
private ImageButton m_TrashIcon;
public event CollapseBoxClickedEventHandler CollapseBoxClickedEvent;
public event TrashCanClickedEventHandler TrashCanClickedEvent;
private string m_Caption;
//private bool m_bContainsTrashCan;
//private System.Windows.Forms.GroupBox m_GroupBox;
private Size m_FullSize;
private bool m_bResizingFromCollapse = false;
#endregion Members
public CollapsibleGroupBox()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(CollapsibleGroupBox));
this.m_CollapseBox = new UIToolbox.CollapseBox();
this.m_TrashIcon = new UIToolbox.ImageButton();
this.SuspendLayout();
//
// m_CollapseBox
//
this.m_CollapseBox.IsPlus = false;
this.m_CollapseBox.Location = new System.Drawing.Point(12, 1);
this.m_CollapseBox.Name = "m_CollapseBox";
this.m_CollapseBox.Size = new System.Drawing.Size(11, 11);
this.m_CollapseBox.TabIndex = 1;
this.m_CollapseBox.Click += new System.EventHandler(this.CollapseBox_Click);
this.m_CollapseBox.DoubleClick += new System.EventHandler(this.CollapseBox_DoubleClick);
//
// m_TrashIcon
//
this.m_TrashIcon.Location = new System.Drawing.Point(88, 0);
this.m_TrashIcon.Name = "m_TrashIcon";
this.m_TrashIcon.NormalImage = ((System.Drawing.Image)(resources.GetObject("m_TrashIcon.NormalImage")));
this.m_TrashIcon.PressedImage = ((System.Drawing.Image)(resources.GetObject("m_TrashIcon.PressedImage")));
this.m_TrashIcon.Size = new System.Drawing.Size(16, 16);
this.m_TrashIcon.TabIndex = 2;
this.m_TrashIcon.TabStop = false;
this.m_TrashIcon.Click += new System.EventHandler(this.TrashIcon_Click);
//
// CollapsibleGroupBox
//
this.Controls.Add(this.m_TrashIcon);
this.Controls.Add(this.m_CollapseBox);
this.Name = "CollapsibleGroupBox";
this.Resize += new System.EventHandler(this.CollapsibleGroupBox_Resize);
this.Load += new System.EventHandler(this.CollapsibleGroupBox_Load);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.CollapsibleGroupBox_Paint);
this.ResumeLayout(false);
}
#endregion
#region Events
private void CollapsibleGroupBox_Load(object sender, System.EventArgs e)
{
SetGroupBoxCaption();
}
private void CollapsibleGroupBox_Resize(object sender, System.EventArgs e)
{
if(m_bResizingFromCollapse != true)
{
m_FullSize = this.Size;
}
Invalidate();
}
private void CollapsibleGroupBox_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// UG! I originall added a GroupBox control but ran into problems...
// Panes derived from CollapsibleGroupBox would "chew up" controls
// added to them, so I had to get rid of the GroupBox and draw a fake
// group box myself
Graphics g = e.Graphics;
Rectangle theRec = new Rectangle();
theRec = this.ClientRectangle;
//Color theEdgeGrayColor = Color.FromArgb(170, 170, 156);
//Pen thePen = new Pen(theEdgeGrayColor);
Pen thePen = SystemPens.ControlDark;
int theTextSize = (int)g.MeasureString(m_Caption, this.Font).Width;
if(theTextSize < 1)
theTextSize = 1;
int theCaptionPosition = (theRec.X + 8) + 2 + m_CollapseBox.Width + 2;
int theEndPosition = theCaptionPosition + theTextSize + 1;
if(m_TrashIcon.Visible)
theEndPosition += (m_TrashIcon.Width + 2);
g.DrawLine(thePen, theRec.X + 8, theRec.Y + 5,
theRec.X, theRec.Y + 5);
g.DrawLine(thePen, theRec.X, theRec.Y + 5,
theRec.X, theRec.Bottom - 2);
g.DrawLine(thePen, theRec.X, theRec.Bottom - 2,
theRec.Right - 1, theRec.Bottom - 2);
g.DrawLine(thePen, theRec.Right - 2, theRec.Bottom - 2,
theRec.Right - 2, theRec.Y + 5);
g.DrawLine(thePen, theRec.Right - 2, theRec.Y + 5,
theRec.X + theEndPosition, theRec.Y + 5);
g.DrawLine(Pens.White, theRec.X + 8, theRec.Y + 6,
theRec.X + 1, theRec.Y + 6);
g.DrawLine(Pens.White, theRec.X + 1, theRec.Y + 6,
theRec.X + 1, theRec.Bottom - 3);
g.DrawLine(Pens.White, theRec.X, theRec.Bottom - 1,
theRec.Right, theRec.Bottom - 1);
g.DrawLine(Pens.White, theRec.Right - 1, theRec.Bottom - 1,
theRec.Right - 1, theRec.Y + 5);
g.DrawLine(Pens.White, theRec.Right - 3, theRec.Y + 6,
theRec.X + theEndPosition, theRec.Y + 6);
StringFormat sf = new StringFormat();
SolidBrush drawBrush = new SolidBrush(Color.Black);
g.DrawString(m_Caption, this.Font, drawBrush, theCaptionPosition, 0);
}
public void CollapseBox_Click(object sender, System.EventArgs e)
{
// at this point the control's value has changed but hasn't been
// redrawn on the screen
this.IsCollapsed = m_CollapseBox.IsPlus;
if(CollapseBoxClickedEvent != null)
{
CollapseBoxClickedEvent(this);
}
}
private void CollapseBox_DoubleClick(object sender, System.EventArgs e)
{
// fast clicking registers as double-clicking, so map a double-click
// event into a single click.
CollapseBox_Click(sender, e);
}
private void TrashIcon_Click(object sender, System.EventArgs e)
{
if(TrashCanClickedEvent != null)
{
TrashCanClickedEvent(this);
}
}
#endregion events
#region Accessors
[DefaultValue("")]
public string Caption
{
get
{
return m_Caption;
}
set
{
m_Caption = value;
SetGroupBoxCaption();
Invalidate();
}
}
[DefaultValue(true)]
public bool ContainsTrashCan
{
get
{
return m_TrashIcon.Visible;
}
set
{
//m_bContainsTrashCan = value;
m_TrashIcon.Visible = value;
SetGroupBoxCaption();
Invalidate();
}
}
[Browsable(false)]
public int FullHeight
{
get
{
return m_FullSize.Height;
}
}
[DefaultValue(false), Browsable(false)]
public bool IsCollapsed
{
get
{
#if DEBUG
if(m_CollapseBox.IsPlus)
{
Debug.Assert(this.Height == kCollapsedHeight);
}
else
{
Debug.Assert(this.Height > kCollapsedHeight);
}
#endif
return m_CollapseBox.IsPlus;
}
set
{
if(m_CollapseBox.IsPlus != value)
{
m_CollapseBox.IsPlus = value;
}
if(m_CollapseBox.IsPlus != true)
{
//Expand();
this.Size = m_FullSize;
}
else
{
//Collapse();
m_bResizingFromCollapse = true;
Size smallSize = m_FullSize;
smallSize.Height = kCollapsedHeight;
this.Size = smallSize;
m_bResizingFromCollapse = false;
}
Invalidate();
}
}
#endregion accessors
#region Methods
private void SetGroupBoxCaption()
{
RepositionTrashCan();
}
private void RepositionTrashCan()
{
if(m_TrashIcon.Visible)
{
// Since the trash icon's location is a function of the caption's width,
// we also need to reposition the trash icon
// first, find the width of the string
Graphics g = CreateGraphics();
SizeF theTextSize = new SizeF();
theTextSize = g.MeasureString(m_Caption, this.Font);
// Hmm... MeasureString() doesn't seem to be returning the
// correct width. Close... but not exact
// 11 is the number of pixels from the beginning of the group box
// to the beginning of text of the group box's caption
//m_TrashIcon.Left = m_GroupBox.Location.X + 29 + (int)theTextSize.Width - 4;
m_TrashIcon.Left = this.Location.X + 29 + (int)theTextSize.Width - 4;
// -4 is a fudge factor. Hey, what can I say...
}
}
#endregion Methods
public delegate void CollapseBoxClickedEventHandler(object sender);
public delegate void TrashCanClickedEventHandler(object sender);
}
}

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="m_CollapseBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="m_CollapseBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="m_CollapseBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="m_TrashIcon.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="m_TrashIcon.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="m_TrashIcon.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="m_TrashIcon.NormalImage" type="System.Drawing.Bitmap, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAJdJREFUOE+VkgEK
wDAIA9ef92n9WYdlEbVR2aB0OM3O6Hj4s0l4JLkuLIV7rXUdiX8n1XFFpkDjlYj785xzyxES+25FGQYQ
uxaYP0ePoaqofBeaygdNgInAx90ZeQhCn/8IIIAbyPHO5ugmAU9IcWriZaTtvTMQVOqD3YEwgZ7A4ict
pOOkG2nw45Son+Uou3WOipXYyX0Bl4EdsYyOw8oAAAAASUVORK5CYII=
</value>
</data>
<data name="m_TrashIcon.PressedImage" type="System.Drawing.Bitmap, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAJhJREFUOE+VkgEK
wDAIA9dP9gn9/w86LIuojcoGpcNpdkbHw59NwiPJdWEp3Gut60j8O6mOKzIFGq9E3J/nnFuOkNh3K8ow
gNi1wPw5egxVReW70FQ+aAJMBD7uzshDEPr8RwAB3ECOdzZHNwl4QopTEy8jbe+dgaBSH+wOhAn0BBY/
aSEdJ91Igx+nRP0sR9mtc1SsxE7uC3D26NQxC7BSAAAAAElFTkSuQmCC
</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Name">
<value>CollapsibleGroupBox</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
</root>

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace UIToolbox
{
/// <summary>
/// Summary description for ExpandingPanel.
/// </summary>
public class ExpandingPanel : System.Windows.Forms.Panel
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
ArrayList m_GroupArray = null;
public const int kGap = 6;
public ExpandingPanel()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
m_GroupArray = new ArrayList();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// ExpandingPanel
//
this.Move += new System.EventHandler(this.ExpandingPanel_Move);
this.Resize += new System.EventHandler(this.ExpandingPanel_Resize);
this.SizeChanged += new System.EventHandler(this.ExpandingPanel_SizeChanged);
this.Layout += new System.Windows.Forms.LayoutEventHandler(this.ExpandingPanel_Layout);
}
#endregion
public void AddGroup(UIToolbox.CollapsibleGroupBox theGroupBox)
{
m_GroupArray.Add(theGroupBox);
this.SuspendLayout();
Size theSize = this.AutoScrollMinSize;
theGroupBox.Location = new System.Drawing.Point(4, theSize.Height + 4);
theSize.Height += (theGroupBox.Height + kGap);
this.AutoScrollMinSize = theSize;
theGroupBox.CollapseBoxClickedEvent += new CollapsibleGroupBox.CollapseBoxClickedEventHandler(this.CollapseBox_Click);
theGroupBox.TrashCanClickedEvent += new CollapsibleGroupBox.TrashCanClickedEventHandler(this.TrashCan_Click);
this.Controls.Add(theGroupBox);
this.ResumeLayout(false);
}
private void ExpandingPanel_Layout(object sender, System.Windows.Forms.LayoutEventArgs e)
{
}
private void ExpandingPanel_Move(object sender, System.EventArgs e)
{
}
private void ExpandingPanel_Resize(object sender, System.EventArgs e)
{
}
private void ExpandingPanel_SizeChanged(object sender, System.EventArgs e)
{
}
private void CollapseBox_Click(object sender)
{
int nIndex;
nIndex = m_GroupArray.IndexOf(sender);
CollapsibleGroupBox theGroupBox;
theGroupBox = (CollapsibleGroupBox)m_GroupArray[nIndex];
int nDelta;
if(theGroupBox.Height == CollapsibleGroupBox.kCollapsedHeight)
{
nDelta = -(theGroupBox.FullHeight - CollapsibleGroupBox.kCollapsedHeight);
}
else
{
nDelta = (theGroupBox.FullHeight - CollapsibleGroupBox.kCollapsedHeight);
}
for(int i=(nIndex + 1); i<m_GroupArray.Count; i++)
{
theGroupBox = (CollapsibleGroupBox)m_GroupArray[i];
theGroupBox.Top += nDelta;
}
Size theSize = this.AutoScrollMinSize;
theSize.Height += nDelta;
this.AutoScrollMinSize = theSize;
}
private void TrashCan_Click(object sender)
{
int nIndex;
nIndex = m_GroupArray.IndexOf(sender);
CollapsibleGroupBox theGroupBox;
theGroupBox = (CollapsibleGroupBox)m_GroupArray[nIndex];
int nDelta;
nDelta = theGroupBox.Height + kGap;
m_GroupArray.RemoveAt(nIndex);
theGroupBox.Dispose();
theGroupBox = null;
for(int i=nIndex; i<m_GroupArray.Count; i++)
{
theGroupBox = (CollapsibleGroupBox)m_GroupArray[i];
theGroupBox.Top -= nDelta;
}
Size theSize = this.AutoScrollMinSize;
theSize.Height -= nDelta;
this.AutoScrollMinSize = theSize;
}
}
}
#region NOT USED
class IndexerArray
{
protected ArrayList data = new ArrayList();
public object this[int idx]
{
get
{
if (idx > -1 && idx < data.Count)
{
return (data[idx]);
}
else
{
throw new InvalidOperationException("[IndexerArray.get_Item]Index out of range");
}
}
set
{
if (idx > -1 && idx < data.Count)
{
data[idx] = value;
}
else if (idx == data.Count)
{
data.Add(value);
}
else
{
throw new InvalidOperationException("[IndexerArray.set_Item]Index out of range");
}
}
}
}
#endregion NOT USED

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Name">
<value>ExpandingPanel</value>
</data>
</root>

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace UIToolbox
{
/// <summary>
/// Summary description for ImageButton.
/// </summary>
public class ImageButton : OwnerDrawButton
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
#region Internal variables
private Image m_NormalImage = null;
private Image m_PressedImage = null;
#endregion Internal variables
public ImageButton()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// ImageButton
//
this.Paint += new System.Windows.Forms.PaintEventHandler(this.ImageButton_Paint);
}
#endregion
#region Events
private void ImageButton_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
if(m_ButtonState == ButtonState.TrackingInside)
{
if(m_PressedImage != null)
{
g.DrawImage(m_PressedImage, 0, 0, m_PressedImage.Width, m_PressedImage.Height);
}
}
else
{
if(m_NormalImage != null)
{
g.DrawImage(m_NormalImage, 0, 0, m_NormalImage.Width, m_NormalImage.Height);
}
}
}
#endregion Events
#region Accessors
public Image NormalImage
{
get
{
return m_NormalImage;
}
set
{
m_NormalImage = value;
Invalidate();
}
}
public Image PressedImage
{
get
{
return m_PressedImage;
}
set
{
m_PressedImage = value;
Invalidate();
}
}
#endregion Accessors
}
}

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="ResMimeType">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="Version">
<value>1.0.0.0</value>
</resheader>
<resheader name="Reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="Writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace UIToolbox
{
/// <summary>
/// Summary description for OwnerDrawButton.
/// </summary>
public class OwnerDrawButton : System.Windows.Forms.Control
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
#region Internal variables
public enum ButtonState
{
Normal,
TrackingInside,
TrackingOutside
}
protected ButtonState m_ButtonState = ButtonState.Normal;
#endregion Internal variables
public OwnerDrawButton()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// OwnerDrawButton
//
this.Resize += new System.EventHandler(this.OwnerDrawButton_Resize);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OwnerDrawButton_MouseUp);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.OwnerDrawButton_Paint);
this.MouseEnter += new System.EventHandler(this.OwnerDrawButton_MouseEnter);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.OwnerDrawButton_MouseMove);
this.MouseLeave += new System.EventHandler(this.OwnerDrawButton_MouseLeave);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OwnerDrawButton_MouseDown);
}
#endregion
#region Events
private void OwnerDrawButton_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// needs to be implemented by the derived class
}
private void OwnerDrawButton_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
m_ButtonState = ButtonState.TrackingInside;
Invalidate();
}
private void OwnerDrawButton_MouseEnter(object sender, System.EventArgs e)
{
if(m_ButtonState == ButtonState.TrackingOutside)
{
m_ButtonState = ButtonState.TrackingInside;
Invalidate();
}
}
private void OwnerDrawButton_MouseLeave(object sender, System.EventArgs e)
{
if(m_ButtonState == ButtonState.TrackingInside)
{
m_ButtonState = ButtonState.TrackingOutside;
Invalidate();
}
}
private void OwnerDrawButton_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(m_ButtonState == ButtonState.Normal)
return;
Rectangle bounds = new Rectangle(0, 0, this.Width, this.Height);
if(m_ButtonState == ButtonState.TrackingInside)
{
if( !bounds.Contains(e.X, e.Y) )
OwnerDrawButton_MouseLeave(sender, e);
}
else if(m_ButtonState == ButtonState.TrackingOutside)
{
if( bounds.Contains(e.X, e.Y) )
OwnerDrawButton_MouseEnter(sender, e);
}
}
private void OwnerDrawButton_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(m_ButtonState != ButtonState.Normal)
{
m_ButtonState = ButtonState.Normal;
Invalidate();
}
}
private void OwnerDrawButton_Resize(object sender, System.EventArgs e)
{
Invalidate();
}
#endregion Events
}
}

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Name">
<value>OwnerDrawButton</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
vCardEditor/assests/Add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

View File

@@ -14,6 +14,21 @@
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -51,17 +66,21 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Model\Column.cs" />
<Compile Include="Model\FixedList.cs" />
<Compile Include="Model\ObjectCopier.cs" />
<Compile Include="Model\FormState.cs" />
<Compile Include="Model\PropertyComparer.cs" />
<Compile Include="Repository\ConfigRepository.cs" />
<Compile Include="Repository\ContactRepository.cs" />
<Compile Include="Repository\FileHandler.cs" />
<Compile Include="Repository\IContactRepository.cs" />
<Compile Include="Repository\Interfaces\IConfigRepository.cs" />
<Compile Include="Repository\Interfaces\IContactRepository.cs" />
<Compile Include="Model\Contact.cs" />
<Compile Include="Presenter\MainPresenter.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Repository\IFileHandler.cs" />
<Compile Include="Repository\Interfaces\IFileHandler.cs" />
<Compile Include="Thought.vCards\vCard.cs" />
<Compile Include="Thought.vCards\vCardAccessClassification.cs" />
<Compile Include="Thought.vCards\vCardCertificate.cs" />
@@ -118,6 +137,27 @@
<Compile Include="View\ConfigDialog.Designer.cs">
<DependentUpon>ConfigDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\Customs\AddAddressDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\Customs\AddAddressDialog.Designer.cs">
<DependentUpon>AddAddressDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\Customs\AddressBox.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="View\Customs\AddressBox.Designer.cs">
<DependentUpon>AddressBox.cs</DependentUpon>
</Compile>
<Compile Include="View\Customs\AddressTabControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="View\Customs\ColumnsDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\Customs\ColumnsDialog.Designer.cs">
<DependentUpon>ColumnsDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\EventArgs.cs" />
<Compile Include="View\IMainView.cs" />
<Compile Include="View\MainForm.cs">
@@ -126,9 +166,25 @@
<Compile Include="View\MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="View\SortableBindingList.cs" />
<Compile Include="View\StateTextBox.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="View\UIToolbox\CollapseBox.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="View\UIToolbox\CollapsibleGroupBox.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="View\UIToolbox\ExpandingPanel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="View\UIToolbox\ImageButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="View\UIToolbox\OwnerDrawButton.cs">
<SubType>Component</SubType>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
@@ -146,9 +202,33 @@
<EmbeddedResource Include="View\ConfigDialog.resx">
<DependentUpon>ConfigDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\Customs\AddAddressDialog.resx">
<DependentUpon>AddAddressDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\Customs\AddressBox.resx">
<DependentUpon>AddressBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\Customs\ColumnsDialog.resx">
<DependentUpon>ColumnsDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\UIToolbox\CollapseBox.resx">
<DependentUpon>CollapseBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\UIToolbox\CollapsibleGroupBox.resx">
<DependentUpon>CollapsibleGroupBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\UIToolbox\ExpandingPanel.resx">
<DependentUpon>ExpandingPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\UIToolbox\ImageButton.resx">
<DependentUpon>ImageButton.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\UIToolbox\OwnerDrawButton.resx">
<DependentUpon>OwnerDrawButton.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@@ -162,8 +242,20 @@
</ItemGroup>
<ItemGroup>
<Content Include="assests\About.ico" />
<Content Include="assests\Add.png" />
<Content Include="assests\Close.png" />
<Content Include="assests\icons8-close-16.png" />
<Content Include="assests\vCard.ico" />
<Content Include="Releases.txt" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -14,14 +14,49 @@ namespace vCardEditor_Test
[TestClass]
public class ContactRepositoryTest
{
[TestMethod]
public void NewFileOpened_EmtpyVCF_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfEmtpy);
var repo = Substitute.For<ContactRepository>(fileHandler);
var contacts = repo.LoadContacts("file.vcf");
Assert.IsTrue(contacts.Count == 0);
}
[TestMethod]
public void NewFileOpened_IncorrectVCF_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfIncorrect);
var repo = Substitute.For<ContactRepository>(fileHandler);
var contacts = repo.LoadContacts("file.vcf");
Assert.IsTrue(contacts.Count == 0);
}
[TestMethod]
public void NewFileOpened_Utf8Entry_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfUtf8Entry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var contacts = repo.LoadContacts("file.vcf");
Assert.AreEqual(repo.LoadContacts("name")[0].Name, "Oum Alaâ");
Assert.AreEqual(contacts[0].Name, "Oum Alaâ");
}
[TestMethod]
public void NewFileOpened_Address_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var contacts = repo.LoadContacts("file.vcf");
Assert.IsTrue(contacts[0].card.DeliveryAddresses.FirstOrDefault().AddressType.Contains(vCardDeliveryAddressTypes.Work));
}
[TestMethod]
@@ -31,7 +66,7 @@ namespace vCardEditor_Test
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.LoadContacts("file.vcf");
repo.Contacts[0].isDirty=true;
string phone = "0011223344";
@@ -52,7 +87,7 @@ namespace vCardEditor_Test
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.LoadContacts("file.vcf");
repo.Contacts[0].isDirty = true;
repo.SaveDirtyVCard(0, new vCard());
@@ -68,7 +103,7 @@ namespace vCardEditor_Test
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.LoadContacts("file.vcf");
repo.Contacts[2].isDirty = true;
string phone = "0011223344";
@@ -86,7 +121,7 @@ namespace vCardEditor_Test
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.LoadContacts("file.vcf");
repo.Contacts[3].isDirty = true;
repo.SaveDirtyVCard(3, new vCard());
@@ -102,13 +137,13 @@ namespace vCardEditor_Test
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfWikiv21);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.LoadContacts("file.vcf");
repo.Contacts[0].isDirty = true;
repo.SaveDirtyVCard(0, new vCard());
//var card = repo.Contacts[2].card;
//Assert.IsNull(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular));
var card = repo.Contacts[0].card;
Assert.IsNull(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular));
}
}
}

View File

@@ -1,13 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace vCardEditor_Test
namespace vCardEditor_Test
{
public class Entries
{
public static string[] vcfEmtpy
{
get
{
return "".Split('\n');
}
}
public static string[] vcfIncorrect
{
get
{
return "abcdef".Split('\n');
}
}
public static string[] vcfOneEntry
{
get
@@ -131,5 +141,53 @@ namespace vCardEditor_Test
return s.Split('\n');
}
}
public static string[] vcfwithExternalPhoto
{
get
{
string s = @"BEGIN:VCARD\n" +
"VERSION:4.0\n" +
"N:Gump;Forrest;;;\n" +
"FN:Forrest Gump\n" +
"PHOTO;MEDIATYPE=image/jpg:https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/TomHanksForrestGump94.jpg/224px-TomHanksForrestGump94.jpg\n" +
"END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfwithInternalPhoto
{
get
{
string s = @"BEGIN:VCARD\n" +
"VERSION:3.0\n" +
"N:Dupont;Jean;;;\n" +
"FN:Jean Dupont1\n" +
"ADR;TYPE=WORK;TYPE=PREF:;;6A Rue Th. Decuyper;;;;\n" +
"EMAIL;TYPE=INTERNET:jean.dupont@example.com\n" +
"PHOTO;ENCODING=b:/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCABcAFwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD7LooooAKKq6nqFppto93ezpDEgyWZgK8k134t6jqV7Jp3g7STclTtNxcBo1HuDyDQB7KSB1Iorw1YfiNqhV216e1kJzshdWUfiRXXJJ8QdI8OTMIbfU7qIAoZpsF/XOBQB6JRXmPhL4s2l3cf2f4j0+40m+BwS8TLFn2dsV6Ta3MF1Cs1tNHLG3IZGBB/KgCWiiigAooooAKivLiK0tZbmdwkcalmJ7ADNS15z8e9XksvCa2Fs5W4vZkiwDzsYlT/ADoA4TUtdvfiT4ruLWLemgWchjwOkzA8exBBr0jQvB0dtYrHBGlvGB8qJxWP8LfDsOmWdrZRoP3KAyHH3mHc1o63rGo+INbfQPD0yxRQj/SLgZ+XnBAI6EUAdhpGmw2UIUKGcH73etCuY8IeGbrRLiWa41W7vPMA+WWUsAfbNdPQBjeI/Duha3blNWsbecdmkXJFebXWot8MtVjxfi50GdwuxnyYSTgADoB1Neo+INKj1iwa0kuJ4FJB3Qvtb868c8UQeEtJ11NF1CDVtUTdslkklDpGc98/nQB7TpOo2mq2EV9YzJNBKoZWU5BFW68g8JXb+C/F0Wk+eZdC1IB7JichCxwqj8O1evjmgAooooAK8b+MJ+2/EfQ7BjmNbV5CvbKuMV7JXkfxnh+w+LtG1vH7sRm3Y+7uMUAdt4VtWfTp2Q7XfIDenFcjr2l6j4E8LXlzpFwhurq5klmuJELiNTz0POM10XhbVBby/Z5D8jHg102qT2EVkz37Ri3I5L4xigDjPg34q1DxHpcq6iyTywk/v402q/OMAV39cxpHijwj5ptdPvbRGzyqALXQx3VtIMpcRMPZxQBNXnvjL4bR65rLajbXgt2lz5yvk7s9cY6cV3zTwKMtNGB7sKwNS8aeH7HU4dNkvle6mYKqRjd3x2oA5T4maJDpnhLREhJL6bOhRyckhQe9ehaJM1xo9pO33pIVY/iK4z40XIGkadaLy9zeLGB9Qa7PRIjBpFpCeqQqp/AUAXKK5rXPE/8AZ/inTNEWDebxypfONvy5rpRyKACuQ+LWkR6v4RnQyJHLARPGWYDlMkDmusnkWGF5XOFRSx+gFeF+NZta8e6oy2OrT6do8DbcwkZmHXkH8RQBZ8Da0mq6PExlVrqABJgDnDVP8XtWiuPBENpebvJaUpNgn7m2ubl8G6l4LQeINE33Fmf+PuIjlu5fA6nFaNzc6P408PTWSzoryoR5bEB0P0oA8em8OaPeXE0/h+6e2cxqBFuPUd+T3q3YT+ONKknEEx8soBH+9zggV0t/4XtooAWsZtM1KDhJ7SMskyjhd7HpxzWDpXiq3MktnqIaG4hOCSOG9OTQBl3PiD4k3GnxQyzPJKDiT5wMjP09K0fge2t2fxY8q5tEKzhpmcy7tijAP0qbUPFUCYisoZZJW4VmQhB+NbfgC0u21Bra2lWLU9RP766dtoRDwyxt0YGgD1y5l/4TL4jRRW/z6fpTbmfsZVPb8DXp+MDArD8GeG7Lw1pKWVqNznmWUjmRv7x963KAPlT4yeONetPEVjJG5tr2K6kUFeSqjhTj3FaWifGrxraabFBd6ClxKvWR5SpYduMV33xj8IaBca/pOqz2ELXUsxV2I5YAcCu7HhHw3cxxyz6PbSOY1BYg+lAFjxrO1t4YvpV6+Sw/Q15J8Nh/xR+nyHq8eT+Zr1zxlCZ/DV9GP+eLH9DXga3dzY/DLTZbR9rxyRqSPTcc0Ae9WMMd94eEGBhkwR+FeV+IvhpGb17qw8+wnJzvtht3fWvRvhte/bPDdvKxBLKDXRA+YxDICOnIoA8W0Pwz49TfbpPaXdtjGLxmOaZqPws1vUpt1xpXh5CerKrZr29QicKoH0qtq1/Dp2nz3kx+SJSxoA8t8N/BTTLaRZtTnZ8f8sUIMf5Vwnx88N674SubXXtDhZtMtplk2Qg7olDZx7LxXrnwz+I1r40W9EVjPavbNjbIRl+D0x9KzLnxRqF94qudB17SNmj3IaOJ5EGGzwOfxNAHWfDbxDH4n8Gadq6MC08Cs49CR0ro6+cvCl54q8B+L9YtdOs5NQ0GO6b/AEeJctEvHIycAYr0xPiv4ee03oHa5x/x7Bhvz6fWgCH4oS/a/F/hjTI8lzcuXA7ApxXosS7YkX0UCvPfAumanrXiKbxbrlu1uWAW1gcYKAZAb05Br0SgCrq6B9Ku0PeBx/46a+drdBJ4G1Gyx/x6OB9MAmvo+6ANrKD0KH+VfPdiqg+MocfIsxAHp+7oA9B+CV35nhSxQnJNuDXoi57dK8l+BLMNEs0zwIQK9b6HFAAzAAepqlqWmwalYS2lzuMcv3gDir5APWigDitT8I31jYRQeELm0011++0sG8tzW/ounXCabbprDW91eRgbpViCgn1A7VrUUAeeaZGtr8Wbq1kVTHcWjSFSMgktXbjSdLD7xptmG658hc/yrkdWRU+KlrIowxswCfbdXdUAIqqoCqAAOgApaKKAP//Z\n" +
"TEL;TYPE=CELL:+1234 56789\n" +
"END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfOneEntryWithTwoAddress
{
get
{
string s = @"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"ADR;Home;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"END:VCARD";
return s.Split('\n');
}
}
}
}

View File

@@ -1,16 +1,15 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VCFEditor;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VCFEditor.View;
using VCFEditor.Presenter;
using VCFEditor.Model;
using System.ComponentModel;
using VCFEditor.Repository;
using vCardEditor.Repository;
using NSubstitute;
using vCardEditor.View;
using System;
using AutoFixture;
using Thought.vCards;
using System.Collections.Generic;
namespace vCardEditor_Test
{
@@ -25,10 +24,8 @@ namespace vCardEditor_Test
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa"));
_ = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.aaa"));
view.Received().DisplayMessage(Arg.Any<string>(), Arg.Any<string>());
}
@@ -41,14 +38,15 @@ namespace vCardEditor_Test
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.vcf"));
view.Received().DisplayContacts(Arg.Is<BindingList<Contact>>(x=>x.Count == 1));
view.Received().DisplayContacts(Arg.Is<BindingList<Contact>>(x => x[0].card.FormattedName == "Jean Dupont1"));
view.Received().DisplayContacts(Arg.Is<SortableBindingList<Contact>>(x=>x.Count == 1));
view.Received().DisplayContacts(Arg.Is<SortableBindingList<Contact>>(x => x[0].card.FormattedName == "Jean Dupont1"));
}
@@ -60,14 +58,15 @@ namespace vCardEditor_Test
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
view.AskMessage(Arg.Any<string>(), Arg.Any<string>()).Returns(true);
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.vcf"));
repo.Contacts[1].isDirty = true;
view.NewFileOpened += Raise.EventWith(new EventArg<string>("bbb.vcf"));
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename2.vcf"));
view.Received().AskMessage(Arg.Any<string>(), Arg.Any<string>());
@@ -79,6 +78,7 @@ namespace vCardEditor_Test
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
@@ -91,16 +91,17 @@ namespace vCardEditor_Test
}
[TestMethod]
public void SaveFile_ExistAlready()
public void SaveFile_ExistAlready_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
fileHandler.FileExist("aaa.vcf.old0").Returns(true);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
_ = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
view.SaveContactsSelected += Raise.Event();
@@ -110,15 +111,15 @@ namespace vCardEditor_Test
[TestMethod]
public void DeleteTest()
public void DeleteContact_ShouldDelete_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
_ = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
//Mouse click on second row.
@@ -132,9 +133,121 @@ namespace vCardEditor_Test
}
[TestMethod]
public void CopyTextToClipboardHandler_ShouldCopyvCard()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
repo.LoadContacts("aaa.vcf");
view.CopyTextToClipboardEvent += Raise.Event();
view.Received().SendTextToClipBoard(Arg.Any<string>());
view.Received().DisplayMessage("vCard copied to clipboard!", "Information");
}
[TestMethod]
public void AddressRemovedHandler_ShouldRemove_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntryWithTwoAddress);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var contact = repo.LoadContacts("aaa.vcf");
view.AddressRemoved += Raise.EventWith(new EventArg<int>(0));
Assert.AreEqual(1, contact[0].card.DeliveryAddresses.Count);
}
[TestMethod]
public void AddressAddedHandler_ShouldAddAddress_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntryWithTwoAddress);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var contact = repo.LoadContacts("aaa.vcf");
var fixture = new Fixture { RepeatCount = 2 };
var lstvCardDeliveryAddressTypes = fixture.Create <List<vCardDeliveryAddressTypes>>();
view.AddressAdded += Raise.EventWith(new EventArg<List<vCardDeliveryAddressTypes>>(lstvCardDeliveryAddressTypes));
Assert.AreEqual(2 + 1, contact[0].card.DeliveryAddresses.Count);
Assert.AreEqual(2, contact[0].card.DeliveryAddresses[2].AddressType.Count);
}
[TestMethod]
public void AddressModifiedHandler_ShouldModifyAddress_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntryWithTwoAddress);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var contact = repo.LoadContacts("aaa.vcf");
var fixture = new Fixture { RepeatCount = 2 };
var lstvCardDeliveryAddressTypes = fixture.Create<List<vCardDeliveryAddressTypes>>();
view.AddressModified += Raise.EventWith(new EventArg<List<vCardDeliveryAddressTypes>>(lstvCardDeliveryAddressTypes));
Assert.AreEqual(1, contact[0].card.DeliveryAddresses.Count);
Assert.AreEqual(2, contact[0].card.DeliveryAddresses[0].AddressType.Count);
}
[TestMethod]
public void ExportImage_ShouldExportArrayByte_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfwithInternalPhoto);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
_ = repo.LoadContacts("aaa.vcf");
view.ExportImage += Raise.Event();
fileHandler.Received().WriteBytesToFile(Arg.Any<string>(), Arg.Any<Byte[]>());
}
[TestMethod]
public void ModifyImage_ShouldModify_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfwithInternalPhoto);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var contact = repo.LoadContacts("aaa.vcf");
view.ModifyImage += Raise.EventWith(new EventArg<string>(""));
Assert.AreEqual(0, contact[0].card.Photos.Count);
Assert.IsTrue(contact[0].isDirty);
}
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoFixture" version="4.18.0" targetFramework="net481" />
<package id="Castle.Core" version="5.1.1" targetFramework="net481" />
<package id="Fare" version="2.1.1" targetFramework="net481" />
<package id="NSubstitute" version="5.0.0" targetFramework="net481" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net481" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net481" />

View File

@@ -36,15 +36,22 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="AutoFixture, Version=4.18.0.0, Culture=neutral, PublicKeyToken=b24654c590009d4f, processorArchitecture=MSIL">
<HintPath>..\packages\AutoFixture.4.18.0\lib\net452\AutoFixture.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Fare, Version=2.1.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
<HintPath>..\packages\Fare.2.1.1\lib\net35\Fare.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="NSubstitute, Version=5.0.0.0, Culture=neutral, PublicKeyToken=92dd2e9066daa5ca, processorArchitecture=MSIL">
<HintPath>..\packages\NSubstitute.5.0.0\lib\net462\NSubstitute.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -82,6 +89,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />