diff --git a/ENI-2/ENI2/ENI2/App.config b/ENI-2/ENI2/ENI2/App.config index e175721e..7b435d1f 100644 --- a/ENI-2/ENI2/ENI2/App.config +++ b/ENI-2/ENI2/ENI2/App.config @@ -1,6 +1,6 @@  @@ -35,7 +35,15 @@ Sample license text. - - + + + + + + + + \ No newline at end of file diff --git a/ENI-2/ENI2/ENI2/App.xaml.cs b/ENI-2/ENI2/ENI2/App.xaml.cs index ed258f01..63f11d5e 100644 --- a/ENI-2/ENI2/ENI2/App.xaml.cs +++ b/ENI-2/ENI2/ENI2/App.xaml.cs @@ -10,6 +10,8 @@ using System.Windows.Controls; using System.Windows.Input; using System; using System.Net; +using ENI2.LockingServiceReference; +using System.Threading; namespace ENI2 { @@ -17,7 +19,15 @@ namespace ENI2 /// Interaction logic for App.xaml /// public partial class App : Application - { + { + // "global" statics, da gibt es sicher noch einen eleganteren Weg.. + private static ServiceClient _lockingServiceClient = null; + private static Guid? _userId = null; + + // Splash screen + private static SplashScreenWindow _splashScreenWindow; + private ManualResetEvent ResetSplashCreated; + private Thread _splashThread; public App() : base() { @@ -27,8 +37,23 @@ namespace ENI2 new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))); } + public static ServiceClient LockingServiceClient { get { return _lockingServiceClient; } } + + public static SplashScreenWindow SplashScreen { get { return _splashScreenWindow; } } + + public static Guid? UserId { get { return _userId; } } + protected override void OnStartup(StartupEventArgs e) { + this.ResetSplashCreated = new ManualResetEvent(false); + this._splashThread = new Thread(ShowSplash); + _splashThread.SetApartmentState(ApartmentState.STA); + _splashThread.IsBackground = true; + _splashThread.Name = "Splash Screen"; + _splashThread.Start(); + + ResetSplashCreated.WaitOne(); + base.OnStartup(e); // initialize static / localized lookups from sqlite database @@ -44,8 +69,18 @@ namespace ENI2 // perform logon // TODO: Benutzerverwaltung - - + + // Connect to locking service (if enabled) + + try + { + if (ENI2.Properties.Settings.Default.UseLocking) + App._lockingServiceClient = new ServiceClient("BasicHttpBinding_IService", ENI2.Properties.Settings.Default.LockingServerAddress); + } + catch (Exception ex) + { + System.Diagnostics.Trace.WriteLine("Exception creating locking service client: {0}", ex.ToString()); + } } @@ -83,5 +118,14 @@ namespace ENI2 } } + private void ShowSplash() + { + _splashScreenWindow = new SplashScreenWindow(); + _splashScreenWindow.Show(); + + ResetSplashCreated.Set(); + System.Windows.Threading.Dispatcher.Run(); + } + } } diff --git a/ENI-2/ENI2/ENI2/DetailBaseControl.cs b/ENI-2/ENI2/ENI2/DetailBaseControl.cs index a1512418..4426c79e 100644 --- a/ENI-2/ENI2/ENI2/DetailBaseControl.cs +++ b/ENI-2/ENI2/ENI2/DetailBaseControl.cs @@ -8,14 +8,30 @@ using System.Windows.Controls; using bsmd.database; using System.Windows.Media.Imaging; +using System.ComponentModel; namespace ENI2 { public class DetailBaseControl : UserControl { + #region Fields + protected bool _initialized = false; + private DependencyPropertyDescriptor _dpTextBox; + private DependencyPropertyDescriptor _dpDatePicker; + private DependencyPropertyDescriptor _dpLocode; + private DependencyPropertyDescriptor _dpCheckbox; + private DependencyPropertyDescriptor _dpComboboxIndex; + private DependencyPropertyDescriptor _dpComboboxValue; + private DependencyPropertyDescriptor _dpNumericUpdown; + private Dictionary _controlClassDict = new Dictionary(); + private Dictionary _typeMessageDict = new Dictionary(); + private List _controlMessages = new List(); + + #endregion + #region enum protected enum LocodeState @@ -46,14 +62,30 @@ namespace ENI2 /// public event Action RequestLock; + /// + /// Eine in der Detailansicht enthaltene Meldeklasse hat sich geändert + /// + public event Action NotificationClassChanged; + #endregion #region Properties + /// + /// Core to be edited + /// public MessageCore Core { get; set; } + /// + /// all messages for this core + /// public List Messages { get; set; } + /// + /// particular messages that are edited on this page + /// + public List ControlMessages { get { return this._controlMessages; } } + public Guid UserId { get; set; } // TODO: Ersetzen mit der User-Entity #endregion @@ -61,7 +93,20 @@ namespace ENI2 #region public methods public virtual void Initialize() { - + + _dpTextBox = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox)); + _dpDatePicker = DependencyPropertyDescriptor.FromProperty(Xceed.Wpf.Toolkit.DateTimePicker.ValueProperty, typeof(Xceed.Wpf.Toolkit.DateTimePicker)); + _dpLocode = DependencyPropertyDescriptor.FromProperty(Controls.LocodeControl.LocodeValueProperty, typeof(Controls.LocodeControl)); + _dpCheckbox = DependencyPropertyDescriptor.FromProperty(CheckBox.IsCheckedProperty, typeof(CheckBox)); + _dpComboboxIndex = DependencyPropertyDescriptor.FromProperty(ComboBox.SelectedIndexProperty, typeof(ComboBox)); + _dpComboboxValue = DependencyPropertyDescriptor.FromProperty(ComboBox.SelectedValueProperty, typeof(ComboBox)); + _dpNumericUpdown = DependencyPropertyDescriptor.FromProperty(Xceed.Wpf.Toolkit.DoubleUpDown.ValueProperty, typeof(Xceed.Wpf.Toolkit.DoubleUpDown)); + + foreach(Message message in this.Messages) + { + _typeMessageDict[message.MessageNotificationClass] = message; + } + } #endregion @@ -103,9 +148,84 @@ namespace ENI2 } } + #region event handling for control content changes (signal dirty etc) + + protected void RegisterTextboxChange(TextBox textBox, Message.NotificationClass notificationClass) + { + this._dpTextBox.AddValueChanged(textBox, this.controlContentChanged); + this._controlClassDict[textBox] = notificationClass; + } + + protected void RegisterDateTimePickerChange(Xceed.Wpf.Toolkit.DateTimePicker dateTimePicker, Message.NotificationClass notificationClass) + { + this._dpDatePicker.AddValueChanged(dateTimePicker, this.controlContentChanged); + this._controlClassDict[dateTimePicker] = notificationClass; + } + + protected void RegisterLocodeChange(Controls.LocodeControl locodeControl, Message.NotificationClass notificationClass) + { + this._dpLocode.AddValueChanged(locodeControl, this.controlContentChanged); + this._controlClassDict[locodeControl] = notificationClass; + } + + protected void RegisterCheckboxChange(CheckBox checkBox, Message.NotificationClass notificationClass) + { + this._dpCheckbox.AddValueChanged(checkBox, this.controlContentChanged); + this._controlClassDict[checkBox] = notificationClass; + } + + protected void RegisterComboboxIndexChange(ComboBox comboBox, Message.NotificationClass notificationClass) + { + this._dpComboboxIndex.AddValueChanged(comboBox, this.controlContentChanged); + this._controlClassDict[comboBox] = notificationClass; + } + + protected void RegisterComboboxValueChange(ComboBox comboBox, Message.NotificationClass notificationClass) + { + this._dpComboboxValue.AddValueChanged(comboBox, this.controlContentChanged); + this._controlClassDict[comboBox] = notificationClass; + } + + protected void RegisterDoubleUpDownChange(Xceed.Wpf.Toolkit.DoubleUpDown doubleUpDown, Message.NotificationClass notificationClass) + { + this._dpNumericUpdown.AddValueChanged(doubleUpDown, this.controlContentChanged); + this._controlClassDict[doubleUpDown] = notificationClass; + } + + protected void SublistElementChanged(Message.NotificationClass notificationClass) + { + if (_typeMessageDict.ContainsKey(notificationClass)) + { + if (!_typeMessageDict[notificationClass].IsDirty) + { + if (!_typeMessageDict[notificationClass].IsDirty) + { + _typeMessageDict[notificationClass].IsDirty = true; + // signal this notification class changed.. + this.NotificationClassChanged?.Invoke(notificationClass); + } + } + } + } + + private void controlContentChanged(object ctrl, EventArgs args) + { + if (this._controlClassDict.ContainsKey(ctrl)) + { + Message.NotificationClass notificationClass = this._controlClassDict[ctrl]; + this.SublistElementChanged(notificationClass); + } + else + { + System.Diagnostics.Trace.WriteLine("no notification class registered for control!!"); + } + } #endregion + #endregion + + } } diff --git a/ENI-2/ENI2/ENI2/DetailRootControl.xaml b/ENI-2/ENI2/ENI2/DetailRootControl.xaml index 9b783284..2c041851 100644 --- a/ENI-2/ENI2/ENI2/DetailRootControl.xaml +++ b/ENI-2/ENI2/ENI2/DetailRootControl.xaml @@ -18,8 +18,25 @@ - - + + + + + + + + + + + diff --git a/ENI-2/ENI2/ENI2/DetailRootControl.xaml.cs b/ENI-2/ENI2/ENI2/DetailRootControl.xaml.cs index 603ba5a5..ce1bbd7f 100644 --- a/ENI-2/ENI2/ENI2/DetailRootControl.xaml.cs +++ b/ENI-2/ENI2/ENI2/DetailRootControl.xaml.cs @@ -10,6 +10,7 @@ using System.Windows.Controls; using bsmd.database; using ENI2.DetailViewControls; using ENI2.LockingServiceReference; +using System.Windows; namespace ENI2 { @@ -24,8 +25,7 @@ namespace ENI2 private MessageCore _core; private List _listBoxList = new List(); private List _messages; - private Dictionary controlCache = new Dictionary(); - private ServiceClient lockingServiceClient; + private Dictionary controlCache = new Dictionary(); private Guid userId = Guid.NewGuid(); // remove THIS!! #endregion @@ -67,20 +67,7 @@ namespace ENI2 this.listBoxMessages.ItemsSource = this._listBoxList; _messages = DBManager.Instance.GetMessagesForCore(_core, DBManager.MessageLoad.ALL); - Dispatcher.BeginInvoke((Action)(() => this.listBoxMessages.SelectedIndex = 0)); - - // Connect to locking service (if enabled) - - try - { - if (ENI2.Properties.Settings.Default.UseLocking) - this.lockingServiceClient = new ServiceClient("BasicHttpBinding_IService", ENI2.Properties.Settings.Default.LockingServerAddress); - } - catch (Exception ex) - { - System.Diagnostics.Trace.WriteLine("Exception creating locking service client: {0}", ex.ToString()); - } - + Dispatcher.BeginInvoke((Action)(() => this.listBoxMessages.SelectedIndex = 0)); } #endregion @@ -122,19 +109,83 @@ namespace ENI2 detailControl.RequestReload += DetailControl_RequestReload; detailControl.RequestLock += DetailControl_RequestLock; + detailControl.NotificationClassChanged += DetailControl_NotificationClassChanged; detailControl.Initialize(); controlCache.Add(mg.MessageGroupControlType, detailControl); + this.buttonSave.Visibility = Visibility.Hidden; } + else + { + // Control has been created before: Set visibility of "save" button: + bool hasDirtyMessages = false; + DetailBaseControl dbc = controlCache[mg.MessageGroupControlType]; + foreach (Message message in dbc.ControlMessages) + if (message.IsDirty) + hasDirtyMessages = true; + this.buttonSave.Visibility = hasDirtyMessages ? Visibility.Visible : Visibility.Hidden; + } + // plug it in ;-) detailView.Children.Clear(); detailView.Children.Add(controlCache[mg.MessageGroupControlType]); } } + private void buttonSave_Click(object sender, RoutedEventArgs e) + { + MessageBoxResult result = MessageBox.Show(Properties.Resources.textSavePage, Properties.Resources.textConfirmation, + MessageBoxButton.YesNo, MessageBoxImage.Question); + if (result == MessageBoxResult.Yes) + { + DetailBaseControl currentControl = this.detailView.Children[0] as DetailBaseControl; + if (currentControl != null) + { + foreach (Message message in currentControl.ControlMessages) + { + if (message.IsDirty) + { + DBManager.Instance.Save(message); + message.SaveElements(); + message.IsDirty = false; + } + } + this.buttonSave.Visibility = Visibility.Hidden; + } + + } + } + + private void buttonSaveAll_Click(object sender, RoutedEventArgs e) + { + MessageBoxResult result = MessageBox.Show(Properties.Resources.textSaveAll, Properties.Resources.textConfirmation, + MessageBoxButton.YesNo, MessageBoxImage.Question); + if (result == MessageBoxResult.Yes) + { + foreach(Message message in this._messages) + { + if (message.IsDirty) + { + DBManager.Instance.Save(message); + message.SaveElements(); + message.IsDirty = false; + this.buttonSaveAll.Visibility = Visibility.Hidden; + this.buttonSave.Visibility = Visibility.Hidden; + } + } + } + } + + private void DetailControl_NotificationClassChanged(Message.NotificationClass notificationClass) + { + // in der Übersicht die Meldeklasse als geändert markieren..? + this.buttonSaveAll.Visibility = Visibility.Visible; + this.buttonSave.Visibility = Visibility.Visible; + } + private void DetailControl_RequestLock(bool shouldLock) { - if(this.lockingServiceClient == null) + if(App.LockingServiceClient == null) { return; } @@ -142,7 +193,7 @@ namespace ENI2 { try { - string lockResult = this.lockingServiceClient.Lock(this.Core.Id.Value, this.userId.ToString()); + string lockResult = App.LockingServiceClient.Lock(this.Core.Id.Value, this.userId.ToString()); if (lockResult == "") { // lock successful @@ -163,7 +214,7 @@ namespace ENI2 } else { - this.lockingServiceClient.Unlock(this.Core.Id.Value, this.userId.ToString()); + App.LockingServiceClient.Unlock(this.Core.Id.Value, this.userId.ToString()); this.Core.Locked = false; } } diff --git a/ENI-2/ENI2/ENI2/DetailViewControls/OverViewDetailControl.xaml b/ENI-2/ENI2/ENI2/DetailViewControls/OverViewDetailControl.xaml index 339f0f72..43c4b610 100644 --- a/ENI-2/ENI2/ENI2/DetailViewControls/OverViewDetailControl.xaml +++ b/ENI-2/ENI2/ENI2/DetailViewControls/OverViewDetailControl.xaml @@ -74,7 +74,7 @@