23 Commits
v0.4 ... v0.5

Author SHA1 Message Date
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
36 changed files with 1903 additions and 1072 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,3 +1,8 @@
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/B0B2KV8WP)
<p align="center">
<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>
</p>
# vCard Editor
@@ -5,25 +10,31 @@ A Simple vcf file Editor. You can export easily edit (modify, delete) entries of
The software is still in **early stage**.
## Installation
No need to install anything. Just head to the release section and download the last release version.
🔧 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)
![vcardeditorv0_5](https://user-images.githubusercontent.com/169070/236289228-106c1489-e01d-400c-968e-92d3e2be74ab.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)
- 🧰 [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.4
- Import images
- refactoring and bugs fixed
#### 0.3
- Added address section.

View File

@@ -3,23 +3,16 @@ 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");
}
}
@@ -29,7 +22,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 +37,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

@@ -1,13 +1,14 @@
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.Drawing;
using System.Collections.Generic;
namespace VCFEditor.Presenter
{
@@ -31,29 +32,89 @@ namespace VCFEditor.Presenter
_view.TextBoxValueChanged += TextBoxValueChanged;
_view.BeforeLeavingContact += BeforeLeavingContact;
_view.CloseForm += CloseForm;
_view.ModifyImage += ModifyImage;
_view.ExportImage += ExportImage;
_view.AddressAdded += _view_AddressAdded;
_view.AddressModified += _view_AddressModified;
_view.AddressRemoved += _view_AddressRemoved;
}
private void _view_AddressRemoved(object sender, EventArg<int> e)
{
var contact = _repository.Contacts[_view.SelectedContactIndex];
_repository.SetDirtyFlag(_view.SelectedContactIndex);
contact.card.DeliveryAddresses.RemoveAt(e.Data);
}
private void _view_AddressAdded(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 _view_AddressModified(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 ExportImage(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 = Path.ChangeExtension(_repository.fileName, image.Extension);
string imageFile = _view.DisplaySaveDialog(newPath);
_repository.SaveImageToDisk(imageFile, image);
}
}
}
private void ModifyImage(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);
}
void CloseForm(object sender, EventArg<bool> e)
{
if (_repository.dirty && _view.AskMessage("Exit before saving?", "Exit"))
if (_repository.dirty && _view.AskMessage("Exit without saving?", "Exit"))
e.Data = true;
}
public void BeforeLeavingContact(object sender, EventArg<vCard> e)
{
if (_view.SelectedContactIndex > -1)
{
if (_repository.dirty)
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
}
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
}
public void TextBoxValueChanged(object sender, EventArgs e)
{
StateTextBox tb = sender as StateTextBox;
var tb = sender as StateTextBox;
if (tb != null && tb.oldText != tb.Text)
_repository.SaveDirtyFlag(_view.SelectedContactIndex);
_repository.SetDirtyFlag(_view.SelectedContactIndex);
}
@@ -76,7 +137,7 @@ namespace VCFEditor.Presenter
private void SaveContacts(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(_repository.fileName))
_repository.SaveContacts(_repository.fileName);
_repository.SaveContactsToFile(_repository.fileName);
}
@@ -85,34 +146,32 @@ namespace VCFEditor.Presenter
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)
{
BeforeOpeningNewFile(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 +181,21 @@ namespace VCFEditor.Presenter
}
public void ChangeContactSelected(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>

View File

@@ -17,6 +17,7 @@ namespace vCardEditor.Repository
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
@@ -64,7 +65,7 @@ namespace vCardEditor.Repository
/// <returns></returns>
private static ConfigRepository LoadConfig()
{
ConfigRepository obj;
ConfigRepository configData = null;
try
{
@@ -74,19 +75,22 @@ 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,6 @@ using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.Repository;
using System.Collections.Generic;
namespace VCFEditor.Repository
{
@@ -14,7 +13,6 @@ namespace VCFEditor.Repository
{
public string fileName { get; set; }
private IFileHandler _fileHandler;
#region Contact Info
/// <summary>
/// Formatted name.
/// </summary>
@@ -24,9 +22,6 @@ namespace VCFEditor.Repository
/// 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
{
@@ -41,7 +36,6 @@ namespace VCFEditor.Repository
_contacts = value;
}
}
#endregion
public ContactRepository(IFileHandler fileHandler)
{
@@ -50,20 +44,19 @@ namespace VCFEditor.Repository
public BindingList<Contact> LoadContacts(string fileName)
{
Contacts.Clear();
//TODO: Clean end of line from spaces..
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 +65,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 +79,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 +93,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 +124,26 @@ 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;
SetDirtyFlag(i);
_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 +156,7 @@ namespace VCFEditor.Repository
return card;
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
@@ -206,7 +181,7 @@ namespace VCFEditor.Repository
/// </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)
private string GenerateStringFromVCard(vCard card)
{
vCardStandardWriter writer = new vCardStandardWriter();
TextWriter tw = new StringWriter();
@@ -371,18 +338,30 @@ namespace VCFEditor.Repository
return tw.ToString();
}
public void ModifyImage(int index, vCardPhoto photo)
{
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());
}
/// <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
{
get { return _dirty || (_contacts != null && _contacts.Any(x => x.isDirty)); }
set { _dirty = value; }
get { return _contacts != null && _contacts.Any(x => x.isDirty); }
}
}

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,11 @@ namespace vCardEditor.Repository
return File.Exists(filename);
}
public string GetExtension(string path)
{
return Path.GetExtension(path);
}
public void MoveFile(string newFilename, string oldFilename)
{
File.Move(newFilename, oldFilename);
@@ -27,5 +29,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

@@ -10,16 +10,18 @@ namespace VCFEditor.Repository
{
public interface IContactRepository
{
bool dirty { get; }
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 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);
void SaveImageToDisk(string imageFile, vCardPhoto image);
}
}

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,7 @@ namespace vCardEditor.Repository
bool FileExist(string filename);
string[] ReadAllLines(string filename);
void WriteAllText(string fileName, string contents);
string GetExtension(string path);
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

@@ -35,9 +35,10 @@
//
// btnClose
//
this.btnClose.Location = new System.Drawing.Point(253, 347);
this.btnClose.Location = new System.Drawing.Point(337, 427);
this.btnClose.Margin = new System.Windows.Forms.Padding(4, 4, 4, 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;
@@ -45,16 +46,18 @@
//
// 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, 4, 4, 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.Location = new System.Drawing.Point(229, 427);
this.btnCancel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 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;
@@ -62,14 +65,15 @@
//
// 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, 4, 4, 4);
this.Name = "ConfigDialog";
this.Text = "ConfigDialog";
this.Text = "Configuration Dialog";
this.ResumeLayout(false);
}

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()));
//_card.DeliveryAddresses[i].AddressType = diag.Addresses;
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);
}
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[TabCount - 1].Dispose();
}
}
}

View File

@@ -10,7 +10,7 @@ namespace VCFEditor.View
{
public interface IMainView
{
#region All events
event EventHandler AddContact;
event EventHandler DeleteContact;
event EventHandler BeforeOpeningNewFile;
@@ -21,14 +21,20 @@ 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;
int SelectedContactIndex { get; }
void DisplayContacts(BindingList<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);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,13 @@ using VCFEditor.Model;
using Thought.vCards;
using vCardEditor.Repository;
using vCardEditor.Model;
using System.Drawing;
using System.Collections.Generic;
namespace vCardEditor.View
{
public partial class MainForm : Form, IMainView
{
#region event list
public event EventHandler AddContact;
public event EventHandler SaveContactsSelected;
public event EventHandler BeforeOpeningNewFile;
@@ -23,9 +24,15 @@ 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;
ComponentResourceManager resources;
public int SelectedContactIndex
{
get
@@ -42,23 +49,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)
{
if (contacts != null)
this.bsContacts.DataSource = contacts;
bsContacts.DataSource = contacts;
}
@@ -67,7 +73,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 +81,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 +105,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 +119,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 +183,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 +192,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 +217,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 +233,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 +253,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,39 +290,37 @@ 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;
@@ -403,24 +339,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 +360,52 @@ 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);
}
}
}

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

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>
<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>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -118,6 +133,21 @@
<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\EventArgs.cs" />
<Compile Include="View\IMainView.cs" />
<Compile Include="View\MainForm.cs">
@@ -146,6 +176,12 @@
<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\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
@@ -162,8 +198,18 @@
</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" />
</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>
<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,48 @@ namespace vCardEditor_Test
return s.Split('\n');
}
}
public static string[] vcfwithExternalPhoto
{
get
{
string s = @"BEGIN:VCARD
VERSION:4.0
N:Gump;Forrest;;;
FN:Forrest Gump
ORG:Bubba Gump Shrimp Co.
TITLE:Shrimp Man
PHOTO;MEDIATYPE=image/jpg:https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/TomHanksForrestGump94.jpg/224px-TomHanksForrestGump94.jpg
TEL;TYPE=work,voice;VALUE=uri:tel:+1-111-555-1212
TEL;TYPE=home,voice;VALUE=uri:tel:+1-404-555-1212
ADR;TYPE=work;LABEL=""100 Waters Edge\nBaytown, LA 30314\nUnited States of America""
:;;100 Waters Edge; Baytown;LA;30314;United States of America
ADR;TYPE=home;LABEL=""42 Plantation St.\nBaytown, LA 30314\nUnited States of America""
:;;42 Plantation St.; Baytown;LA;30314;United States of America
EMAIL:forrestgump @example.com
REV:20080424T195243Z
END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfwithInternalPhoto
{
get
{
string s = @"BEGIN:VCARD
VERSION:3.0
N:Dupont;Jean;;;
FN:Jean Dupont1
ADR;TYPE=WORK;TYPE=PREF:;;6A Rue Th. Decuyper;;;;
EMAIL;TYPE=INTERNET:jean.dupont@example.com
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
TEL;TYPE=CELL:+1234 56789
END:VCARD";
return s.Split('\n');
}
}
}
}

View File

@@ -28,7 +28,7 @@ namespace vCardEditor_Test
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa"));
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.aaa"));
view.Received().DisplayMessage(Arg.Any<string>(), Arg.Any<string>());
}
@@ -45,7 +45,7 @@ namespace vCardEditor_Test
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"));
@@ -64,10 +64,10 @@ namespace vCardEditor_Test
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>());