git_bsmd/ENI-2/ENI2/ENI2/MainWindow.xaml.cs

558 lines
23 KiB
C#

// Copyright (c) 2017 schick Informatik
// Description: The main application window
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Threading;
using System.Timers;
using bsmd.database;
using System.Windows.Controls;
using ENI2.Controls;
using ENI2.EditControls;
using ENI2.Util;
using log4net;
using System.ComponentModel;
using bsmd.ExcelReadService;
namespace ENI2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Fields
private ReportingPartyControl rpControl;
private RuleControl ruleControl;
private ServerStatusControl statusControl;
private SucheControl sucheControl;
private List<MessageCore> anmeldungen = new List<MessageCore>();
private bool efMode = false;
private bool dbConnected;
ScaleTransform _transform = new ScaleTransform(1.0, 1.0);
private Dictionary<Guid, ClosableTabItem> openTabs = new Dictionary<Guid, ClosableTabItem>();
private Dictionary<ClosableTabItem, Guid> lockedCores = new Dictionary<ClosableTabItem, Guid>();
private int failedLogonCount = 0;
private ReportingParty userEntity = null;
private ILog _log = LogManager.GetLogger(typeof(MainWindow));
private DatabaseEntityWatchdog _dbWatchDog;
#endregion
#region Construction
public MainWindow()
{
Thread.Sleep(500);
InitializeComponent();
App.SplashScreen.ShowMessage("loading..");
this.sucheControl = new SucheControl();
this.tabSearch.Content = this.sucheControl;
this.sucheControl.buttonSuche.IsDefault = true;
this.sucheControl.MessageCoreSelected += AnmeldungenControl_MessageCoreSelected;
this.mainPanel.LayoutTransform = this._transform;
this._dbWatchDog = new DatabaseEntityWatchdog();
this._dbWatchDog.DatabaseEntityChanged += _dbWatchDog_DatabaseEntityChanged;
this._dbWatchDog.VisitTransitIdUpdated += _dbWatchDog_VisitTransitIdUpdated;
App.SplashScreen.ShowMessage("done");
Thread.Sleep(500);
App.SplashScreen.LoadComplete();
}
#endregion
#region Search related event handler
private void AnmeldungenControl_MessageCoreSelected(MessageCore aMessageCore)
{
if(aMessageCore != null)
{
if (!openTabs.ContainsKey(aMessageCore.Id.Value))
{
ClosableTabItem searchResultItem = new ClosableTabItem();
// try to lock the item
Guid lockedUserId = Guid.Empty;
if (!(aMessageCore.Cancelled ?? false))
{
try
{
lockedUserId = App.LockingServiceClient.Lock(aMessageCore.Id.Value, this.userEntity.Id.Value);
if (lockedUserId == Guid.Empty)
{
this.lockedCores[searchResultItem] = aMessageCore.Id.Value;
}
}
catch (Exception ex)
{
// TODO: wenn der Locking Service nicht erreichbar ist sollte das Ganze trotzdem noch irgendwie funktionieren
_log.ErrorFormat("LockingService.Lock: {0}", ex.Message);
}
}
bool iDidLockIt = (lockedUserId == Guid.Empty) && !(aMessageCore.Cancelled ?? false);
searchResultItem.TabClosing += SearchResultItem_TabClosing;
DateTime? eta = aMessageCore.IsTransit ? aMessageCore.ETAKielCanal : aMessageCore.ETA;
searchResultItem.SetHeaderText(string.Format("{0} [{1}-{2}]", aMessageCore.Shipname, aMessageCore.PoC, eta.HasValue ? eta.Value.ToShortDateString() : ""),
iDidLockIt);
searchResultItem.IsCancelled = aMessageCore.Cancelled ?? false;
DetailRootControl drc = new DetailRootControl(aMessageCore);
drc.LockedByOtherUser = !iDidLockIt;
if (!(aMessageCore.Cancelled ?? false))
{
drc.LockedBy = iDidLockIt ? this.userEntity : DBManager.Instance.GetReportingPartyDict()[lockedUserId];
}
searchResultItem.Content = drc;
this.mainFrame.Items.Add(searchResultItem);
Dispatcher.BeginInvoke((Action)(() => this.mainFrame.SelectedIndex = (this.mainFrame.Items.Count - 1)));
this.openTabs.Add(aMessageCore.Id.Value, searchResultItem);
this._dbWatchDog.Register(aMessageCore);
drc.HighlightReset += Drc_HighlightReset;
drc.OpenNewCoreRequested += (core) =>
{
this.AnmeldungenControl_MessageCoreSelected(core);
};
}
else
{
Dispatcher.BeginInvoke((Action)(() => this.mainFrame.SelectedItem = openTabs[aMessageCore.Id.Value]));
}
}
}
private void Drc_HighlightReset(DatabaseEntity entity)
{
MessageCore resetCore = entity as MessageCore;
if (resetCore != null)
{
if (openTabs.ContainsKey(resetCore.Id.Value))
{
openTabs[resetCore.Id.Value].IsHighlighted = false;
}
}
}
private void SearchResultItem_TabClosing(object sender, CancelEventArgs e)
{
ClosableTabItem tabItem = sender as ClosableTabItem;
if(tabItem != null)
{
DetailRootControl drc = tabItem.Content as DetailRootControl;
// Test for unsaved changes
if(drc.HasUnsavedChanges)
{
if (MessageBox.Show(Properties.Resources.textConfirmWithoutSaving, Properties.Resources.textConfirmation, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
e.Cancel = true;
}
if (!e.Cancel)
{
if (lockedCores.ContainsKey(tabItem))
{
try
{
App.LockingServiceClient.Unlock(lockedCores[tabItem], this.userEntity.Id.Value);
lockedCores.Remove(tabItem);
}
catch (Exception ex)
{
_log.ErrorFormat("LockingService.Unlock: {0}", ex.Message);
}
}
if (openTabs.ContainsKey(drc.Core.Id.Value))
{
this._dbWatchDog.UnRegister(drc.Core);
openTabs.Remove(drc.Core.Id.Value);
}
}
}
}
#endregion
#region Window control click event handler
private void logoImage_MouseUp(object sender, MouseButtonEventArgs e)
{
if(efMode) Process.Start("http://www.eintracht-frankfurt.de/home.html");
else Process.Start("http://www.eureport.de/");
}
private void buttonAbout_Click(object sender, RoutedEventArgs e)
{
AboutDialog ad = new AboutDialog();
ad.Show();
}
private void radioButton_Click(object sender, RoutedEventArgs e)
{
this.rootContainer.Children.Clear();
bool newButtonsVisible = false;
if(sender == this.buttonNotifications)
{
this.rootContainer.Children.Add(this.mainFrame);
newButtonsVisible = true;
}
else if(sender == this.buttonUserAdmin)
{
if (this.rpControl == null)
{
this.rpControl = new ReportingPartyControl();
Dictionary<Guid, ReportingParty> repPartyDict = DBManager.Instance.GetReportingPartyDict();
this.rpControl.ReportingParties = new ObservableCollection<ReportingParty>(repPartyDict.Values);
}
this.rootContainer.Children.Add(this.rpControl);
}
else if(sender == this.buttonEditRules)
{
if (this.ruleControl == null)
{
this.ruleControl = new RuleControl();
this.ruleControl.UserEntity = this.userEntity;
this.ruleControl.ValidationRules = DBManager.Instance.GetValidationRules();
}
this.rootContainer.Children.Add(ruleControl);
}
else if(sender == this.buttonStatus)
{
if(this.statusControl == null)
{
this.statusControl = new ServerStatusControl();
}
this.rootContainer.Children.Add(this.statusControl);
}
this.buttonNewId.Visibility = newButtonsVisible ? Visibility.Visible : Visibility.Hidden;
this.buttonNewWithId.Visibility = newButtonsVisible ? Visibility.Visible : Visibility.Hidden;
}
#endregion
#region window lifetime event handler
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// if (Debugger.IsAttached) this.busyIndicator.IsBusy = false; // not for me :-P
this.dbConnected = DBManager.Instance.Connect(Properties.Settings.Default.ConnectionString);
labelGeneralStatus.Text = dbConnected ? "DB Connected" : "DB Connect failed";
labelVersion.Text = "V. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
labelUsername.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
if (Keyboard.IsKeyDown(Key.LeftShift))
{
efMode = true;
logoImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/ef_logo.png"));
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
try
{
// unlock all cores
foreach (ClosableTabItem tabItem in this.lockedCores.Keys)
{
App.LockingServiceClient.Unlock(lockedCores[tabItem], this.userEntity.Id.Value);
}
}
catch(Exception ex)
{
_log.ErrorFormat("LockingService.Unlock: {0}", ex.Message);
}
DBManager.Instance.Disconnect();
Properties.Settings.Default.MainWindowPlacement = this.GetPlacement();
Properties.Settings.Default.Save();
}
private void Window_SourceInitialized(object sender, EventArgs e)
{
this.SetPlacement(Properties.Settings.Default.MainWindowPlacement);
this.textUsername.Focus();
}
#endregion
#region Command event handler
private void ExecutedClearCommand(object sender, ExecutedRoutedEventArgs e)
{
Xceed.Wpf.Toolkit.DateTimePicker dtPicker = e.OriginalSource as Xceed.Wpf.Toolkit.DateTimePicker;
if (dtPicker == null)
dtPicker = CustomCommands.FindParent<Xceed.Wpf.Toolkit.DateTimePicker>(e.OriginalSource as DependencyObject);
if(dtPicker != null)
{
dtPicker.Value = null;
}
// das funktioniert auch für Comboboxen :P
ComboBox cb = e.OriginalSource as ComboBox;
if(cb == null)
{
cb = CustomCommands.FindParent<ComboBox>(e.OriginalSource as DependencyObject);
}
if(cb != null)
{
cb.SelectedIndex = -1;
LocalValueEnumerator localSetProperties = cb.GetLocalValueEnumerator();
while(localSetProperties.MoveNext())
{
if(localSetProperties.Current.Property.Name == "SelectedIndex")
{
cb.ClearValue(localSetProperties.Current.Property);
}
}
}
}
private void CanExecuteClearCommand(object sender, CanExecuteRoutedEventArgs e)
{
// validate?
e.CanExecute = true;
}
private void buttonNewTransitIdClick(object sender, RoutedEventArgs e)
{
MessageCore newCore = new MessageCore();
VisitIdDialog visitIdDialog = new VisitIdDialog();
visitIdDialog.Core = newCore;
visitIdDialog.IsModal = false;
visitIdDialog.Closed += (senderDialog, closeArgs) =>
{
VisitIdDialog closedDialog = senderDialog as VisitIdDialog;
if(closedDialog.IsOK)
{
if (!closedDialog.Core.IsDK)
{
// deutsche Häfen fordern eine Visit-Id an, für DK erfolgt hier nur die Anlage eines Datensatzes
closedDialog.Core.BSMDStatusInternal = MessageCore.BSMDStatus.TOSEND;
}
if (closedDialog.Core.PoC.Equals("ZZNOK"))
closedDialog.Core.IsTransit = true;
closedDialog.Core.Incoming = true;
closedDialog.Core.DefaultReportingPartyId = this.userEntity.Id;
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(closedDialog.Core);
// Meldeklassen für neuen Anlauf erzeugen:
bsmd.database.Util.CreateMessagesForCore(closedDialog.Core, null, userEntity);
this.AnmeldungenControl_MessageCoreSelected(closedDialog.Core); // in einem neuen Reiter öffnen
}
};
visitIdDialog.Show();
}
/// <summary>
/// Callback Neuanlage mit vorhandener ID (zur Abfrage der verfügbaren Meldeklassen)
/// </summary>
private void buttonNewWithIdClick(object sender, RoutedEventArgs e)
{
NewWithIdDialog newWithIdDialog = new NewWithIdDialog();
newWithIdDialog.IsModal = false;
newWithIdDialog.OKClicked += new Action(() =>
{
if (newWithIdDialog.ValidId)
{
MessageCore newCore = new MessageCore();
newCore.Incoming = true;
newCore.InitialHIS = Message.NSWProvider.DUDR_TEST;
bool alreadyInSystem = false;
if (bsmd.database.Util.IsTransitId(newWithIdDialog.VisitTransitId))
{
newCore.TransitId = newWithIdDialog.VisitTransitId;
newCore.IsTransit = true;
alreadyInSystem = (DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoreByTransitId(newWithIdDialog.VisitTransitId) != null);
}
else
{
newCore.VisitId = newWithIdDialog.VisitTransitId;
newCore.IsTransit = false;
alreadyInSystem = (DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoreByVisitId(newWithIdDialog.VisitTransitId) != null);
}
if (alreadyInSystem)
{
MessageBox.Show(Properties.Resources.textVisitTransitAlreadyInDatabase, Properties.Resources.textCaptionError, MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
newCore.DefaultReportingPartyId = this.userEntity.Id;
newCore.PoC = newWithIdDialog.VisitTransitId.Substring(0, 5);
newCore.Portname = LocodeDB.PortNameFromLocode(newCore.PoC);
newCore.IMO = newWithIdDialog.IMO;
newCore.ENI = newWithIdDialog.ENI;
newCore.InitialHIS = newWithIdDialog.SelectedHIS;
if (newCore.IsTransit)
newCore.ETAKielCanal = newWithIdDialog.ETA;
else
newCore.ETA = newWithIdDialog.ETA;
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(newCore);
// Meldeklassen für neuen Anlauf erzeugen:
bsmd.database.Util.CreateMessagesForCore(newCore, null, userEntity);
this.AnmeldungenControl_MessageCoreSelected(newCore); // in einem neuen Reiter öffnen
}
}
});
newWithIdDialog.Show();
}
private void closeButton_Click(object sender, RoutedEventArgs e)
{
// close particular tab
TabItem tabitem = e.Source as TabItem;
if(tabitem != null)
{
this.mainFrame.Items.Remove(tabitem);
}
}
private void _dbWatchDog_DatabaseEntityChanged(DatabaseEntity entity)
{
MessageCore changedCore = entity as MessageCore;
if(changedCore != null)
{
// tab färben
if(this.openTabs.ContainsKey(changedCore.Id.Value))
{
TabItem tabitem = this.openTabs[changedCore.Id.Value];
this.Dispatcher.BeginInvoke(new Action(() =>
{
if (tabitem is ClosableTabItem)
((ClosableTabItem)tabitem).IsHighlighted = true;
}));
}
}
}
private void _dbWatchDog_VisitTransitIdUpdated(DatabaseEntity entity)
{
MessageCore changedCore = entity as MessageCore;
if (changedCore != null)
{
TabItem tabitem = this.openTabs[changedCore.Id.Value];
this.Dispatcher.BeginInvoke(new Action(() =>
{
DetailRootControl drc = tabitem.Content as DetailRootControl;
if (drc != null)
{
drc.CoreChanged(changedCore);
}
}));
}
}
#endregion
#region mouse wheel / zooming events
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
base.OnPreviewMouseWheel(e);
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
this._transform.ScaleX += (e.Delta > 0) ? 0.05 : -0.05;
this._transform.ScaleY += (e.Delta > 0) ? 0.05 : -0.05;
}
}
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseDown(e);
if (e.ChangedButton == MouseButton.Middle)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
this._transform.ScaleX = 1.0;
this._transform.ScaleY = 1.0;
}
}
}
#endregion
#region logon box event handlers
private void buttonLogin_Click(object sender, RoutedEventArgs e)
{
if(this.textPassword.Password.IsNullOrEmpty() || this.textUsername.Text.IsNullOrEmpty())
{
this.labelLoginResult.Content = Properties.Resources.textUserNamePasswordEmpty;
return;
}
ReportingParty.LogonResult logonResult = ReportingParty.Login(this.textUsername.Text, this.textPassword.Password, out this.userEntity);
switch(logonResult)
{
case ReportingParty.LogonResult.OK:
this.busyIndicator.IsBusy = false;
this.labelStatusBar.Text = string.Format("Rep.Party: {0} {1} [{2}]", this.userEntity.FirstName, this.userEntity.LastName, this.userEntity.Logon);
App.UserId = this.userEntity.Id;
if (this.userEntity.IsAdmin)
{
this.buttonUserAdmin.Visibility = Visibility.Visible;
this.buttonEditRules.Visibility = Visibility.Visible;
}
break;
case ReportingParty.LogonResult.FAILED:
this.labelLoginResult.Content = Properties.Resources.textWrongPassword;
failedLogonCount++;
break;
case ReportingParty.LogonResult.USERUKN:
this.labelLoginResult.Content = Properties.Resources.textUsernameUnknown;
failedLogonCount++;
break;
}
if (failedLogonCount == 3)
{
this.buttonLogin.IsEnabled = false;
MessageBox.Show(Properties.Resources.textWrongPasswordThreeTimes, Properties.Resources.textCaptionError);
}
}
private void buttonExit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
#endregion
}
}