source: trunk/sources/HeuristicLab.Hive.Client.Console/HiveClientConsole.cs @ 1511

Last change on this file since 1511 was 1511, checked in by whackl, 12 years ago

added recurring appoinment (#468)

File size: 20.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Diagnostics;
25using System.Drawing;
26using System.Linq;
27using System.Net;
28using System.ServiceModel;
29using System.Windows.Forms;
30using Calendar;
31using HeuristicLab.Hive.Client.Console.ClientService;
32using ZedGraph;
33
34namespace HeuristicLab.Hive.Client.Console
35{
36
37  #region Delegates
38
39  public delegate void UpdateTextDelegate(EventLogEntry ev);
40  public delegate void OnDialogClosedDelegate(RecurrentEvent e);
41
42  #endregion
43
44  public partial class HiveClientConsole : Form
45  {
46
47    #region Declarations
48
49    private const string ENDPOINTADRESS = "net.tcp://127.0.0.1:8000/ClientConsole/ClientConsoleCommunicator";
50    private const string EVENTLOGNAME = "Hive Client";
51
52    private EventLog HiveClientEventLog;
53    private ClientConsoleCommunicatorClient cccc;
54    private System.Windows.Forms.Timer refreshTimer;
55    private ListViewColumnSorterDate lvwColumnSorter;
56
57    private List<Appointment> onlineTimes = new List<Appointment>();
58
59    public OnDialogClosedDelegate dialogClosedDelegate;
60
61    #endregion
62
63    #region Constructor
64
65    public HiveClientConsole()
66    {
67      InitializeComponent();
68      lvwColumnSorter = new ListViewColumnSorterDate();
69      lvLog.ListViewItemSorter = lvwColumnSorter;
70      lvwColumnSorter.SortColumn = 3;
71      lvwColumnSorter.Order = SortOrder.Descending;
72      InitTimer();
73      ConnectToClient();
74      RefreshGui();
75      GetEventLog();
76      InitCalender();
77    }
78
79    #endregion
80
81    #region Methods
82
83    private void InitTimer()
84    {
85      refreshTimer = new System.Windows.Forms.Timer();
86      refreshTimer.Interval = 1000;
87      refreshTimer.Tick += new EventHandler(refreshTimer_Tick);
88      refreshTimer.Start();
89    }
90
91    private void RefreshGui()
92    {
93      try
94      {
95        cccc.GetStatusInfosAsync();
96      }
97      catch (Exception ex)
98      {
99        refreshTimer.Stop();
100        DialogResult res = MessageBox.Show("Connection Error, check if Hive Client is running!", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
101        if (res == DialogResult.OK)
102          this.Close();
103      }
104    }
105
106    private void ConnectToClient()
107    {
108      try
109      {
110        cccc = new ClientConsoleCommunicatorClient(new NetTcpBinding(), new EndpointAddress(ENDPOINTADRESS));
111        cccc.GetStatusInfosCompleted += new EventHandler<GetStatusInfosCompletedEventArgs>(cccc_GetStatusInfosCompleted);
112        cccc.GetCurrentConnectionCompleted += new EventHandler<GetCurrentConnectionCompletedEventArgs>(cccc_GetCurrentConnectionCompleted);
113      }
114      catch (Exception)
115      {
116        refreshTimer.Stop();
117        DialogResult res = MessageBox.Show("Connection Error, check if Hive Client is running!", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
118        if (res == DialogResult.OK)
119          this.Close();
120      }
121    }
122
123    private void GetEventLog()
124    {
125      HiveClientEventLog = new EventLog(EVENTLOGNAME);
126      HiveClientEventLog.Source = EVENTLOGNAME;
127      HiveClientEventLog.EntryWritten += new EntryWrittenEventHandler(OnEntryWritten);
128      HiveClientEventLog.EnableRaisingEvents = true;
129
130      ListViewItem curEventLogEntry;
131
132      //databinding on listview?
133      if (HiveClientEventLog != null && HiveClientEventLog.Entries != null)
134      {
135        foreach (EventLogEntry ele in HiveClientEventLog.Entries)
136        {
137          curEventLogEntry = GenerateEventEntry(ele);
138          lvLog.Items.Add(curEventLogEntry);
139        }
140        lvJobDetail.Sort();
141      }
142    }
143
144    private ListViewItem GenerateEventEntry(EventLogEntry ele)
145    {
146      ListViewItem curEventLogEntry;
147      curEventLogEntry = new ListViewItem("", 0);
148      if (ele.EntryType == EventLogEntryType.Error)
149        curEventLogEntry = new ListViewItem("", 1);
150      curEventLogEntry.SubItems.Add(ele.InstanceId.ToString());
151      curEventLogEntry.SubItems.Add(ele.Message);
152      curEventLogEntry.SubItems.Add(ele.TimeGenerated.ToString());
153      return curEventLogEntry;
154    }
155
156    private void UpdateGraph(JobStatus[] jobs)
157    {
158      ZedGraphControl zgc = new ZedGraphControl();
159      GraphPane myPane = zgc.GraphPane;
160      myPane.GraphObjList.Clear();
161
162      myPane.Title.IsVisible = false;  // no title
163      myPane.Border.IsVisible = false; // no border
164      myPane.Chart.Border.IsVisible = false; // no border around the chart
165      myPane.XAxis.IsVisible = false;  // no x-axis
166      myPane.YAxis.IsVisible = false;  // no y-axis
167      myPane.Legend.IsVisible = false; // no legend
168
169      myPane.Fill.Color = this.BackColor;
170
171      myPane.Chart.Fill.Type = FillType.None;
172      myPane.Fill.Type = FillType.Solid;
173
174      double allProgress = 0;
175      double done = 0;
176
177      if (jobs.Length == 0)
178      {
179        myPane.AddPieSlice(100, Color.Green, 0.1, "");
180      }
181      else
182      {
183        for (int i = 0; i < jobs.Length; i++)
184        {
185          allProgress += jobs[i].Progress;
186        }
187
188        done = allProgress / jobs.Length;
189
190        myPane.AddPieSlice(done, Color.Green, 0, "");
191        myPane.AddPieSlice(1 - done, Color.Red, 0, "");
192      }
193      //Hides the slice labels
194      PieItem.Default.LabelType = PieLabelType.None;
195
196      myPane.AxisChange();
197
198      pbGraph.Image = zgc.GetImage();
199    }
200
201    private void InitCalender()
202    {
203      dvOnline.StartDate = DateTime.Now;
204      dvOnline.OnNewAppointment += new EventHandler<NewAppointmentEventArgs>(DvOnline_OnNewAppointment);
205      dvOnline.OnResolveAppointments += new EventHandler<ResolveAppointmentsEventArgs>(DvOnline_OnResolveAppointments);
206    }
207
208    private Appointment CreateAppointment(DateTime startDate, DateTime endDate, bool allDay)
209    {
210      Appointment App = new Appointment();
211      App.StartDate = startDate;
212      App.EndDate = endDate;
213      App.AllDayEvent = allDay;
214      App.BorderColor = Color.Red;
215      App.Locked = true;
216      App.Subject = "Online";
217      App.Recurring = false;
218      return App;
219    }
220
221    private Appointment CreateAppointment(DateTime startDate, DateTime endDate, bool allDay, bool recurring, Guid recurringId)
222    {
223      Appointment App = new Appointment();
224      App.StartDate = startDate;
225      App.EndDate = endDate;
226      App.AllDayEvent = allDay;
227      App.BorderColor = Color.Red;
228      App.Locked = true;
229      App.Subject = "Online";
230      App.Recurring = recurring;
231      App.RecurringId = recurringId;
232      return App;
233    }
234
235    private void DeleteAppointment()
236    {
237      onlineTimes.Remove(dvOnline.SelectedAppointment);
238    }
239
240    private void DeleteRecurringAppointment(Guid recurringId)
241    {
242      onlineTimes.RemoveAll(a => a.RecurringId.ToString() == dvOnline.SelectedAppointment.RecurringId.ToString());
243    }
244
245    #endregion
246
247    #region Events
248
249    private void refreshTimer_Tick(object sender, EventArgs e)
250    {
251      RefreshGui();
252    }
253
254    private void cccc_GetCurrentConnectionCompleted(object sender, GetCurrentConnectionCompletedEventArgs e)
255    {
256      if (e.Error == null)
257      {
258        ConnectionContainer curConnection = e.Result;
259        tbIPAdress.Text = curConnection.IPAdress;
260        tbPort.Text = curConnection.Port.ToString();
261      }
262      else
263      {
264        refreshTimer.Stop();
265        DialogResult res = MessageBox.Show("Connection Error, check if Hive Client is running! - " + e.Error.Message, "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
266        if (res == DialogResult.OK)
267          this.Close();
268      }
269    }
270
271    private void cccc_GetStatusInfosCompleted(object sender, GetStatusInfosCompletedEventArgs e)
272    {
273
274      if (e.Error == null)
275      {
276        StatusCommons sc = e.Result;
277
278        lbGuid.Text = sc.ClientGuid.ToString();
279        lbConnectionStatus.Text = sc.Status.ToString();
280        lbJobdone.Text = sc.JobsDone.ToString();
281        lbJobsAborted.Text = sc.JobsAborted.ToString();
282        lbJobsFetched.Text = sc.JobsFetched.ToString();
283
284        this.Text = "Client Console (" + sc.Status.ToString() + ")";
285
286        ListViewItem curJobStatusItem;
287
288        if (sc.Jobs != null)
289        {
290          lvJobDetail.Items.Clear();
291          double progress;
292          foreach (JobStatus curJob in sc.Jobs)
293          {
294            curJobStatusItem = new ListViewItem(curJob.JobId.ToString());
295            curJobStatusItem.SubItems.Add(curJob.Since.ToString());
296            progress = curJob.Progress * 100;
297            curJobStatusItem.SubItems.Add(progress.ToString());
298            lvJobDetail.Items.Add(curJobStatusItem);
299          }
300          lvJobDetail.Sort();
301        }
302
303        UpdateGraph(sc.Jobs);
304
305        if (sc.Status == NetworkEnumWcfConnState.Connected || sc.Status == NetworkEnumWcfConnState.Loggedin)
306        {
307          btConnect.Enabled = false;
308          btnDisconnect.Enabled = true;
309          lbCs.Text = sc.ConnectedSince.ToString();
310          cccc.GetCurrentConnectionAsync();
311        }
312        else if (sc.Status == NetworkEnumWcfConnState.Disconnected)
313        {
314          btConnect.Enabled = true;
315          btnDisconnect.Enabled = false;
316          lbCs.Text = String.Empty;
317        }
318        else if (sc.Status == NetworkEnumWcfConnState.Failed)
319        {
320          btConnect.Enabled = true;
321          btnDisconnect.Enabled = false;
322          lbCs.Text = String.Empty;
323        }
324
325        cccc.GetCurrentConnection();
326      }
327      else
328      {
329        refreshTimer.Stop();
330        DialogResult res = MessageBox.Show("Connection Error, check if Hive Client is running! - " + e.Error.Message, "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
331        if (res == DialogResult.OK)
332          this.Close();
333      }
334    }
335
336    private void HiveClientConsole_Load(object sender, EventArgs e)
337    {
338      //nothing to do
339    }
340
341    private void UpdateText(EventLogEntry ev)
342    {
343      if (this.lvLog.InvokeRequired)
344      {
345        this.lvLog.Invoke(new
346          UpdateTextDelegate(UpdateText), new object[] { ev });
347      }
348      else
349      {
350        ListViewItem curEventLogEntry = GenerateEventEntry(ev);
351        lvLog.Items.Add(curEventLogEntry);
352        lvJobDetail.Sort();
353      }
354    }
355
356    public void OnEntryWritten(object source, EntryWrittenEventArgs e)
357    {
358      UpdateText(e.Entry);
359    }
360
361    private void lvLog_DoubleClick(object sender, EventArgs e)
362    {
363      ListViewItem lvi = lvLog.SelectedItems[0];
364      HiveEventEntry hee = new HiveEventEntry(lvi.SubItems[2].Text, lvi.SubItems[3].Text, lvi.SubItems[1].Text);
365
366      Form EventlogDetails = new EventLogEntryForm(hee);
367      EventlogDetails.Show();
368    }
369
370    private void btConnect_Click(object sender, EventArgs e)
371    {
372      IPAddress ipAdress;
373      int port;
374      ConnectionContainer cc = new ConnectionContainer();
375      if (IPAddress.TryParse(tbIPAdress.Text, out ipAdress) && int.TryParse(tbPort.Text, out port))
376      {
377        cc.IPAdress = tbIPAdress.Text;
378        cc.Port = port;
379        cccc.SetConnectionAsync(cc);
380      }
381      else
382      {
383        MessageBox.Show("IP Adress and/or Port Error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
384      }
385    }
386
387    private void btnDisconnect_Click(object sender, EventArgs e)
388    {
389      cccc.DisconnectAsync();
390    }
391
392    private void lvLog_ColumnClick(object sender, ColumnClickEventArgs e)
393    {
394      // Determine if clicked column is already the column that is being sorted.
395      if (e.Column == lvwColumnSorter.SortColumn)
396      {
397        // Reverse the current sort direction for this column.
398        if (lvwColumnSorter.Order == SortOrder.Ascending)
399        {
400          lvwColumnSorter.Order = SortOrder.Descending;
401        }
402        else
403        {
404          lvwColumnSorter.Order = SortOrder.Ascending;
405        }
406      }
407      else
408      {
409        // Set the column number that is to be sorted; default to ascending.
410        lvwColumnSorter.SortColumn = e.Column;
411        lvwColumnSorter.Order = SortOrder.Ascending;
412      }
413
414      // Perform the sort with these new sort options.
415      lvLog.Sort();
416    }
417
418    private void btn_clientShutdown_Click(object sender, EventArgs e)
419    {
420      DialogResult res = MessageBox.Show("Do you really want to shutdown the Hive Client?", "Hive Client Console", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
421      if (res == DialogResult.Yes)
422      {
423        cccc.ShutdownClient();
424        this.Close();
425      }
426    }
427
428    private void btbDelete_Click(object sender, EventArgs e)
429    {
430      Appointment selectedAppointment = dvOnline.SelectedAppointment;
431      if (dvOnline.SelectedAppointment != null)
432      {
433        if (!selectedAppointment.Recurring)
434          DeleteAppointment();
435        else
436        {
437          DialogResult res = MessageBox.Show("Delete all events in this series?", "Delete recurrences", MessageBoxButtons.YesNo);
438          if (res != DialogResult.Yes)
439            DeleteAppointment();
440          else
441            DeleteRecurringAppointment(selectedAppointment.RecurringId);
442        }
443      }
444      dvOnline.Invalidate();
445    }
446
447    private void chbade_CheckedChanged(object sender, EventArgs e)
448    {
449      txttimeFrom.Visible = !chbade.Checked;
450      txttimeTo.Visible = !chbade.Checked;
451    }
452
453    private void dvOnline_OnSelectionChanged(object sender, EventArgs e)
454    {
455      if (dvOnline.Selection == SelectionType.DateRange)
456      {
457        dtpFrom.Text = dvOnline.SelectionStart.ToShortDateString();
458        dtpTo.Text = dvOnline.SelectionEnd.Date.ToShortDateString();
459        txttimeFrom.Text = dvOnline.SelectionStart.ToShortTimeString();
460        txttimeTo.Text = dvOnline.SelectionEnd.ToShortTimeString();
461
462        btCreate.Text = "Save";
463      }
464
465      if (dvOnline.Selection == SelectionType.Appointment)
466      {
467
468        dtpFrom.Text = dvOnline.SelectedAppointment.StartDate.ToShortDateString();
469        dtpTo.Text = dvOnline.SelectedAppointment.EndDate.ToShortDateString();
470        txttimeFrom.Text = dvOnline.SelectedAppointment.StartDate.ToShortTimeString();
471        txttimeTo.Text = dvOnline.SelectedAppointment.EndDate.ToShortTimeString();
472
473        //also change the caption of the save button
474        btCreate.Text = "Save changes";
475      }
476
477      if (dvOnline.Selection == SelectionType.None)
478      {
479        //also change the caption of the save button
480        btCreate.Text = "Save";
481      }
482
483    }
484
485    private void Connection_KeyPress(object sender, KeyPressEventArgs e)
486    {
487      if (e.KeyChar == (char)Keys.Return)
488        btConnect_Click(null, null);
489    }
490
491    private void mcOnline_DateChanged(object sender, DateRangeEventArgs e)
492    {
493      dvOnline.StartDate = mcOnline.SelectionStart;
494    }
495
496    private bool CreateAppointment()
497    {
498      DateTime from, to;
499
500      if (!string.IsNullOrEmpty(dtpFrom.Text) && !string.IsNullOrEmpty(dtpTo.Text))
501      {
502        if (chbade.Checked)
503        {
504          //whole day appointment, only dates are visible
505          if (DateTime.TryParse(dtpFrom.Text + " " + txttimeFrom.Text, out from) && DateTime.TryParse(dtpTo.Text + " " + txttimeTo.Text, out to) && from < to)
506            onlineTimes.Add(CreateAppointment(from, to.AddDays(1), true));
507          else
508            MessageBox.Show("Incorrect date format", "Schedule Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
509        }
510        else if (!string.IsNullOrEmpty(txttimeFrom.Text) && !string.IsNullOrEmpty(txttimeTo.Text))
511        {
512          //Timeframe appointment
513          if (DateTime.TryParse(dtpFrom.Text + " " + txttimeFrom.Text, out from) && DateTime.TryParse(dtpTo.Text + " " + txttimeTo.Text, out to) && from < to)
514          {
515            if (from.Date == to.Date)
516              onlineTimes.Add(CreateAppointment(from, to, false));
517            else
518            {
519              //more than 1 day selected
520              while (from.Date != to.Date)
521              {
522                onlineTimes.Add(CreateAppointment(from, new DateTime(from.Year, from.Month, from.Day, to.Hour, to.Minute, 0, 0), false));
523                from = from.AddDays(1);
524              }
525              onlineTimes.Add(CreateAppointment(from, new DateTime(from.Year, from.Month, from.Day, to.Hour, to.Minute, 0, 0), false));
526            }
527          }
528          else
529            MessageBox.Show("Incorrect date format", "Schedule Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
530        }
531        dvOnline.Invalidate();
532        return true;
533      }
534      else
535      {
536        MessageBox.Show("Error in create appointment, please fill out all textboxes!", "Schedule Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
537        return false;
538      }
539    }
540
541    private void btCreate_Click(object sender, EventArgs e)
542    {
543      if (dvOnline.Selection != SelectionType.Appointment)
544      {
545        CreateAppointment();
546      }
547      else
548      {
549        //now we want to change an existing appointment
550        if (!dvOnline.SelectedAppointment.Recurring)
551        {
552          if (CreateAppointment())
553            DeleteAppointment();
554        }
555        else
556        {
557          //change recurring appointment
558          //check, if only selected appointment has to change or whole recurrence
559          DialogResult res = MessageBox.Show("Change all events in this series?", "Change recurrences", MessageBoxButtons.YesNo);
560          if (res != DialogResult.Yes)
561          {
562            if (CreateAppointment())
563              DeleteAppointment();
564          }
565          else
566            ChangeRecurrenceAppointment(dvOnline.SelectedAppointment.RecurringId);
567        }
568      }
569    }
570
571    private void ChangeRecurrenceAppointment(Guid recurringId)
572    {
573      List<Appointment> recurringAppointments = onlineTimes.Where(appointment => appointment.RecurringId == recurringId).ToList();
574      recurringAppointments.ForEach(appointment => appointment.StartDate = DateTime.Parse(appointment.StartDate.Date + " " + txttimeFrom.Text));
575      recurringAppointments.ForEach(appointment => appointment.EndDate = DateTime.Parse(appointment.EndDate.Date + " " + txttimeTo.Text));
576
577      DeleteRecurringAppointment(recurringId);
578      onlineTimes.AddRange(recurringAppointments);
579    }
580
581    private void DvOnline_OnResolveAppointments(object sender, ResolveAppointmentsEventArgs e)
582    {
583      List<Appointment> Apps = new List<Appointment>();
584
585      foreach (Appointment m_App in onlineTimes)
586        if ((m_App.StartDate >= e.StartDate) &&
587            (m_App.StartDate <= e.EndDate))
588          Apps.Add(m_App);
589      e.Appointments = Apps;
590    }
591
592    private void DvOnline_OnNewAppointment(object sender, NewAppointmentEventArgs e)
593    {
594      Appointment Appointment = new Appointment();
595
596      Appointment.StartDate = e.StartDate;
597      Appointment.EndDate = e.EndDate;
598
599      onlineTimes.Add(Appointment);
600    }
601
602    private void btnRecurrence_Click(object sender, EventArgs e)
603    {
604      Recurrence recurrence = new Recurrence();
605      recurrence.dialogClosedDelegate = new OnDialogClosedDelegate(this.DialogClosed);
606      recurrence.Show();
607    }
608
609    public void DialogClosed(RecurrentEvent e)
610    {
611      CreateDailyRecurrenceAppointments(e.DateFrom, e.DateTo, e.AllDay, e.IncWeeks, e.WeekDays);
612    }
613
614    #endregion
615
616    private void CreateDailyRecurrenceAppointments(DateTime dateFrom, DateTime dateTo, bool allDay, int incWeek, HashSet<DayOfWeek> daysOfWeek)
617    {
618      DateTime incDate = dateFrom;
619      Guid guid = Guid.NewGuid();
620
621      while (incDate.Date <= dateTo.Date)
622      {
623        if (daysOfWeek.Contains(incDate.Date.DayOfWeek))
624          onlineTimes.Add(CreateAppointment(incDate, new DateTime(incDate.Year, incDate.Month, incDate.Day, dateTo.Hour, dateTo.Minute, 0), allDay, true, guid));
625        incDate = incDate.AddDays(1);
626      }
627
628      dvOnline.Invalidate();
629    }
630  }
631}
Note: See TracBrowser for help on using the repository browser.