-
Notifications
You must be signed in to change notification settings - Fork 0
/
MainWindow.xaml.cs
2744 lines (2426 loc) · 116 KB
/
MainWindow.xaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*********************************************************************************
* This is the code-behind file for the main program window
*
* Changelog:
* 4/1/13 Ryan Causey: Added checks for the DragDeltaHandlers to fix a error case
* where the width/height value for the window could become
* negative.
* 4/3/13 Ryan Causey: Implementing validation of album names and GUI functions to handle
* when the user wants to make a new album.
* Made sure the new album name text box got cleared when the user
* pressed the X to cancel creation.
* Implementing gui functions to delete an album via the context menu's
* delete button(X button).
* 4/4/13 Ryan Causey: Fixed a bug where on recovery two recovery albums would appear in the library view.
* Implementing switching to the album view on the album view context menu click.
* 4/5/13 Ryan Causey: Implemented GUI function to provide a means to transition back to the Library View from
* the album view. Also making sure the correct dock buttons are displayed between views.
* Added temporary messagebox.show()'s for debugging.
* Fixing the error for the new album name/enter comments GUI element not appearing and
* dissapearing correctly.
* 4/6/13 Ryan Causey: Implemented delete photo context menu button and gui functions. Can now delete photos.
* Implemented an IValueConverter interface to allow us to bind to caches of image files
* as to not lock the file reference causing issues on delete.
* Added functionality to disable the addNewPhotos button while an import operation is in progress.
* User can still browse around and add more albums however.
* Updated handler for the close window operation to stop any import operations if they are occurring.
* Added gui functionality to cancel the import operation while in progress.
* Fixed the remove picture gui function so we pass the correct UID(idInAlbum) to the backend function.
* Fixed an issue in the ImagePathConverter where it would not handle a case where the path was not yet loaded
* to the image to convert.
* Changed two having two context menu's, one for library view and one for album view.
* Fixed a bug where the default image was no longer appearing.
* Bill Sanders: ditched the parameter on guiValidateName
* 4/7/13 Ryan Causey: Fixed a bug where the error style would not clear after clicking the checkbox worked to add an album/photo.
* Fixed a possible infinite loop.
* Converting all hard coded prompt/error strings to use strings in the error/promptStrings files.
* Fixed a bug where multiple view image windows could be opened.
* Changed context menu behavior to match srs specification. It now only shows over an album or photo item in the
* list view. Commented out old handlers that are no longer used.
* 4/8/13 Ryan Causey: Adding comment box functionality to the GUI.
* Fixed a bug with the viewImage function that would lead to an unhandled exception.
* Changed the returnToLibraryView function to close any open viewImage windows.
* Fixed a bug where the application would close the main window but not end the process.
* Implemented changing of image captions. Behavior is as follows: If both the photo's name field is
* empty, it only changes the photo's caption field. If the photo's name field is not empty, it will validate
* the photo name and then validate the caption.
* Changed the regex for caption validation to allow blank captions, in order to allow captions to be removed.
* 4/28/13 Julian Nguyen:
* rename PhotoBomb -> PhotoBomb_Controller.
* Alejandro Sosa:
* Gui fixes, implemented themes, added custom routed event
*
* 4/30/13 Julian Nguyen:
* ErrorReports constants numbers removed and replaced with ReportStatus enums.
* Fun() with "Picture" in the name were changed to "Image"
* 5/1/13 Julian Nguyen
* Renamed the class fields to have '_'!
*
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.Timers;
namespace SoftwareEng
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// Any functions that have no author listed are
/// created by Alejandro Sosa
/// </summary>
public partial class MainWindow : Window
{
//check for determining which view the window is in
private bool _isInsideAlbum;
// A handy shortcut to the settings class...
Properties.Settings Settings = Properties.Settings.Default;
//ugly hacks needed for proper hit testing for Dock animations
private bool isMouseInDockHitBox = false;
private bool isMouseInDock = false;
//the view image window
ViewImage _view = new ViewImage();
//the about window
AboutWindow _photoBomberAboutWindow;
//DATABINDING SOURCE
private ReadOnlyObservableCollection<SimpleAlbumData> _listOfAlbums;
private ReadOnlyObservableCollection<ComplexPhotoData> _listOfPhotos;
private List<ComplexPhotoData> _clipboardOfPhotos = new List<ComplexPhotoData>();
private Guid _clipboardAlbumSrcID = Guid.Empty;
public ReadOnlyObservableCollection<SimpleAlbumData> listOfAlbums
{
get
{
return _listOfAlbums;
}
}
public ReadOnlyObservableCollection<ComplexPhotoData> listOfPhotos
{
get
{
return _listOfPhotos;
}
}
//--didn't know what to call it, so I named it the literal spanish translation
public SoftwareEng.PhotoBomberController masterAndCommander;
//--stores the albumImageList index of the default image for albums
private const short _defaultAlbumImageListIndex = 0;
//--used to specify the UID of the "add new album" icon
//private const int addAlbumID = 0;
//The regex for validation of album names
private String _albumValidationRegex = @promptStrings.albumValidationRegex; //must be at least 1 character, max 32 in length
//The regex for validation of photo names
private String _photoValidationRegex = @promptStrings.photoValidationRegex; //must be at least 1 character, max 32 in length
//The regex for validation of captions
private String _captionValidationRegex = @promptStrings.captionValidationRegex;
//current album UID, defaults to a invalid value(because we eont be in an album)
private Guid _currentAlbumUID = Guid.Empty;
//keep track of if an import operation is occurring
private bool _isImporting = false;
//--A more stable storage for the ID of the user album instead
//-- of relying on a form's selected items collection
//private int albumChosenbyUser;
//temp variable to test out collection views
private CollectionView _ImageListCollectionView;
public MainWindow(PhotoBomberController controllerInstance)
{
InitializeComponent();
// Set the base path for all data to be in the User's application data folder under "PhotoBomber Studios" for now.
// This is equivalent to whatever %localappdata% resolves to in Explorer
string basePath = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
Settings.OrgName);
masterAndCommander = controllerInstance;
masterAndCommander.init(guiConstructorCallback,
System.IO.Path.Combine(basePath, Settings.AlbumXMLFile),
System.IO.Path.Combine(basePath, Settings.PhotoXMLFile),
System.IO.Path.Combine(basePath, Settings.PhotoLibraryName));
isMouseInDockHitBox = false;
isMouseInDock = false;
hideAddAlbumBox();
populateAlbumView(true);
_isInsideAlbum = false;
if (mainWindowAlbumList.Items.IsEmpty == false)
{
mainWindowAlbumList.SelectedItem = mainWindowAlbumList.Items[0];
mainWindowAlbumList.Focus();
}
gui_getCurrentTheme();
}
public MainWindow()
{
InitializeComponent();
// Set the base path for all data to be in the User's application data folder under "PhotoBomber Studios" for now.
// This is equivalent to whatever %localappdata% resolves to in Explorer
string basePath = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
Settings.OrgName);
isMouseInDockHitBox = false;
isMouseInDock = false;
hideAddAlbumBox();
populateAlbumView(true);
_isInsideAlbum = false;
if (mainWindowAlbumList.Items.IsEmpty == false)
{
mainWindowAlbumList.SelectedItem = mainWindowAlbumList.Items[0];
mainWindowAlbumList.Focus();
}
gui_getCurrentTheme();
}
/*********************************************************************************************
* Author: Alejandro Sosa
* parameters: an object of ErrorReport which will be used to check if backend was successful
* return type: void
* purpose: simply calls back end
*********************************************************************************************/
private void guiConstructorCallback(ErrorReport status)
{
if (status.reportStatus != ReportStatus.SUCCESS)
{
//showErrorMessage("Failed at guiConstructorCallback"); //super temporary
masterAndCommander.rebuildBackendOnFilesystem(new generic_callback(rebuildBackend_Callback));
}
}
/*********************************************************************************************
* Author: Alejandro Sosa
* Edited Last By: Ryan Causey
* Edited Last Date: 4/7/13
* parameters: an object of ErrorReport which will be used to check if backend was successful
* return type: void
* purpose: used for blowing up the backend and restarting
*********************************************************************************************/
private void rebuildBackend_Callback(ErrorReport status)
{
if (status.reportStatus != ReportStatus.SUCCESS)
{
//showErrorMessage(errorStrings.rebuildBackendFailure); //super temporary
masterAndCommander.rebuildBackendOnFilesystem(new generic_callback(rebuildBackend_Callback));
}
}
/*********************************************************************************************
* Author: Alejandro Sosa
* Edited Last By: Ryan Causey
* Edited Last Date: 4/6/13
* parameters: bool that determines whether list is cleared or repopulated
* return type: void
* purpose: refreshes list of albums
*********************************************************************************************/
private void populateAlbumView(bool refreshView)
{
if (refreshView == true)
{
masterAndCommander.getAllAlbums(new getAllAlbumNames_callback(guiAlbumsRetrieved));
}
}
/*********************************************************************************************
* Author: Alejandro Sosa
* Edited Last By: Ryan Causey
* Edited Last Date: 4/7/13
* parameters: an object of ErrorReport which will be used to check if backend was successful,
* and a list <type is SimpleAlbumData> containing data to identify all albums requested
* return type: void
* purpose: list of albums returned from the backend
*********************************************************************************************/
public void guiAlbumsRetrieved(ErrorReport status, ReadOnlyObservableCollection<SimpleAlbumData> albumsRetrieved)
{
if (status.reportStatus == ReportStatus.FAILURE)
{
//show an Error
showErrorMessage(errorStrings.retrieveAlbumsFailure);
}
else
{
if (status.reportStatus == ReportStatus.SUCCESS_WITH_WARNINGS)
{
showErrorMessage(errorStrings.retrieveAlbumsWarning);
}
_listOfAlbums = albumsRetrieved;
mainWindowAlbumList.ItemsSource = _listOfAlbums;
}
}
/**************************************************************************************************************************
* Author: Ryan Causey
* Created: 4/3/13
* Function to validate a string against the given regex.
* @Return: True = the string is valid, False = the string is not valid
* @Params: Regex = the regular expression by which to evaluate the string
* stringToValidate = the string which we will validate against the regex
* Last Edited By:
* Last Edited Date:
**************************************************************************************************************************/
private bool validateTheString(String regex, String stringToValidate)
{
RegexStringValidator validator = new RegexStringValidator(regex);
try
{
validator.Validate(stringToValidate);
}
catch (ArgumentException)
{
return false;
}
return true;
}
/**************************************************************************************************************************
* Author: Ryan Causey
* Created on: 4/3/13
* Function for validating that a new album name is valid and unique.
* Last Edited By: Ryan Causey
* Last Edited Date: 4/8/13
**************************************************************************************************************************/
private void guiValidateAlbumName()
{
// Trim the whitespace of this input, SRS Requires no leading/trailing whitespace
nameTextBox.Text = nameTextBox.Text.Trim();
Storyboard nameTextBoxErrorAnimation = this.TryFindResource("InvalidNameFlash") as Storyboard;
try
{
nameTextBoxErrorAnimation.Stop();
handleNameErrorPopup(false, "");
}
catch (Exception)
{
;
}
if (!validateTheString(promptStrings.albumValidationRegex, nameTextBox.Text))
{
// If the text doesn't validate, display an error...
//this is how to call a storyboard defined in resources from the code
//this storyboard is for the name box
try
{
nameTextBoxErrorAnimation.Begin();
}
catch (Exception)
{
;
}
handleNameErrorPopup(true, errorStrings.invalidAlbumNameCharacter);
//showErrorMessage("This is a temporary error check message box failed at guiValidateAlbumName");//temporary as fuuu
//focus the text box and select all the text
nameTextBox.Focus();
nameTextBox.SelectAll();
return;
}
// Otherwise the text was good, but still might not be unique.
// Let's check Library vs Album check again...
//check to see if the album name is unique in the program
masterAndCommander.checkIfAlbumNameIsUnique(new generic_callback(guiValidateAlbumName_Callback), nameTextBox.Text);
}
/**************************************************************************************************************************
* Author: Ryan Causey
* Created on: 4/3/13
* Callback for checking uniqueness of a new album name. This will be called after the back end finishes checking if the album
* name is unique
* Last Edited By: Ryan Causey
* Last Edited Date: 4/7/13
**************************************************************************************************************************/
public void guiValidateAlbumName_Callback(ErrorReport error)
{
//if the album name was not unique
Storyboard nameTextBoxErrorAnimation = this.TryFindResource("InvalidNameFlash") as Storyboard;
try
{
nameTextBoxErrorAnimation.Stop();
handleNameErrorPopup(false, "");
}
catch (Exception)
{
//showErrorMessage("We're going to DIIEEEEEE-bleh");
}
if (error.reportStatus == ReportStatus.FAILURE || error.reportStatus == ReportStatus.SUCCESS_WITH_WARNINGS)
{
//this is how to call a storyboard defined in resources from the code
//this storyboard is for the name box
try
{
nameTextBoxErrorAnimation.Begin();
}
catch (Exception)
{
//showErrorMessage("We're going to DIIEEEEEE-bleh");
}
handleNameErrorPopup(true, errorStrings.invalidAlbumNameUnique);
//apply error template to the text box
//showErrorMessage("This is a temporary error check message box. Failed at guiValidateAlbumName_Callback");//temporary as fuuuu
//focus the text box and select all the text
nameTextBox.Focus();
nameTextBox.SelectAll();
}
//it was unique, great success!
else
{
if (mainWindowAlbumList.SelectedItem != null)
{
guiRenameSelectedAlbum(nameTextBox.Text);
}
else
{
guiCreateNewAlbum(nameTextBox.Text);
}
hideAddAlbumBox();
nameTextBox.Clear();
invalidInputPopup.IsOpen = false;
//stop any error animations
try
{
nameTextBoxErrorAnimation.Stop();
}
catch (Exception) { ;}
}
}
/*
* Created by: Ryan Causey
* Created Date: 4/8/13
* Last Edited By:
* Last Edited Date:
*/
/// <summary>
/// Function to validate the photo name entered. Also calls
/// </summary>
private void guiValidatePhotoName()
{
// Trim the whitespace of this input, SRS Requires no leading/trailing whitespace
photoNameTextBox.Text = photoNameTextBox.Text.Trim();
Storyboard photoNameTextBoxErrorAnimation = this.FindResource("InvalidPhotoNameFlash") as Storyboard;
try
{
photoNameTextBoxErrorAnimation.Stop();
handleNameErrorPopup(false, "");
}
catch (Exception)
{
//showError("We're going to DIIEEEEEE-bleh");
}
if (!validateTheString(promptStrings.albumValidationRegex, photoNameTextBox.Text))
{
// If the text doesn't validate, display an error...
//this is how to call a storyboard defined in resources from the code
//this storyboard is for the name box
try
{
photoNameTextBoxErrorAnimation.Begin();
}
catch (Exception)
{
//showError("We're going to DIIEEEEEE-bleh");
}
handlePhotoNameErrorPopup(true, errorStrings.invalidImageNameCharacter);
//showErrorMessage("This is a temporary error check message box failed at guiValidateAlbumName");//temporary as fuuu
//focus the text box and select all the text
photoNameTextBox.Focus();
photoNameTextBox.SelectAll();
return;
}
// Otherwise the text was good, but still might not be unique.
//check to see if the photo name is unique in the program
masterAndCommander.isImageNameUnique(
new generic_callback(guiValidatePhotoName_Callback),
photoNameTextBox.Text,
_currentAlbumUID);
}
/**************************************************************************************************************************
* Author: Bill Sanders, based on code by Ryan Causey
* Created on: 4/3/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/8/13
* Callback for checking uniqueness of a new photo name. This will be called after the back end finishes checking if the photo
* name is unique
**************************************************************************************************************************/
public void guiValidatePhotoName_Callback(ErrorReport error)
{
Storyboard photoNameTextBoxErrorAnimation = this.FindResource("InvalidPhotoNameFlash") as Storyboard;
try
{
photoNameTextBoxErrorAnimation.Stop();
handleNameErrorPopup(false, "");
}
catch (Exception)
{
//showErrorMessage("We're going to DIIEEEEEE-bleh");
}
//if the photo name was not unique
if (error.reportStatus == ReportStatus.FAILURE || error.reportStatus == ReportStatus.SUCCESS_WITH_WARNINGS)
{
//this is how to call a storyboard defined in resources from the code
//this storyboard is for the name box
try
{
photoNameTextBoxErrorAnimation.Begin();
}
catch (Exception)
{
//showError("We're going to DIIEEEEEE-bleh");
}
handlePhotoNameErrorPopup(true, errorStrings.invalidImageNameUnique);
//apply error template to the text box
//focus the text box and select all the text
photoNameTextBox.Focus();
photoNameTextBox.SelectAll();
}
//it was unique, great success!
else
{
try
{
photoNameTextBoxErrorAnimation.Stop();
handleNameErrorPopup(false, "");
}
catch (Exception)
{
//showError("We're going to DIIEEEEEE-bleh");
}
//now need to validate the caption with the photo, if there is one.
guiValidateCaptionContent();
}
}
/**************************************************************************************************************************
* Author: Ryan Causey
* Created on: 4/3/13
* Function for creating a new album name. Only to be called after the album name is validated.
* @Param: albumName = the name for the new album being created
* Last Edited By:
* Last Edited Date:
**************************************************************************************************************************/
private void guiCreateNewAlbum(String albumName)
{
SimpleAlbumData newAlbum = new SimpleAlbumData();
newAlbum.albumName = albumName;
masterAndCommander.addNewAlbum(new generic_callback(guiCreateNewAlbum_Callback), newAlbum);
}
/**************************************************************************************************************************
* Author: Ryan Causey
* Created on: 4/3/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/7/13
**************************************************************************************************************************/
/// <summary>
/// Callback for guiCreateNewAlbum. If there is an error something really bad happened.
/// Notify the user, rebuild the database, and consolidate all photographs into a single backup album
/// </summary>
/// <param name="error">Error report from the back end.</param>
public void guiCreateNewAlbum_Callback(ErrorReport error)
{
if (error.reportStatus == ReportStatus.FAILURE || error.reportStatus == ReportStatus.SUCCESS_WITH_WARNINGS)
{
//something really bad happened
//notify the user, rebuild the database and consolidate all photographs into a single backup album
showErrorMessage(errorStrings.addAlbumFailure); //super temporary
masterAndCommander.rebuildBackendOnFilesystem(new generic_callback(rebuildBackend_Callback));
}
}
/*
* Created By: Ryan Causey
* Created Date: 4/8/13
* Last Edited By:
* Last Edited Date:
*/
/// <summary>
/// GUI function to validate the caption content and add it if it is valid.
/// If we have gotten this far we have already validated the photo name.
/// </summary>
private void guiValidateCaptionContent()
{
//trim the input of leading and trailing whitespace
commentTextBox.Text = commentTextBox.Text.Trim();
//if it is not a valid string
if (!validateTheString(_captionValidationRegex, commentTextBox.Text))
{
try
{
Storyboard commentTextBoxAnimation = this.FindResource("InvalidCommentFlash") as Storyboard;
commentTextBoxAnimation.Begin();
}
catch (Exception) { ;}
handleCommentErrorPopup(true, errorStrings.invalidComment);
commentTextBox.Focus();
commentTextBox.SelectAll();
}
else
{
guiChangePhotoCaption(commentTextBox.Text);
if (photoNameTextBox.Text != "")
{
guiRenameSelectedPhoto(photoNameTextBox.Text);
}
//clean up the comment box error dialogues and also clear the text boxes
try
{
Storyboard commentTextBoxAnimation = this.FindResource("InvalidCommentFlash") as Storyboard;
commentTextBoxAnimation.Stop();
}
catch (Exception) { ;}
handleCommentErrorPopup(false, "");
commentTextBox.Clear();
photoNameTextBox.Clear();
hideAddAlbumBox();
}
}
/*
* Created By: Ryan Causey
* Created Date: 4/8/13
* Last Edited By:
* Last Edited Date:
*/
/// <summary>
/// Gui function to change a photo's caption
/// </summary>
/// <param name="caption">The new caption value</param>
private void guiChangePhotoCaption(String caption)
{
if (mainWindowAlbumList.SelectedItem != null)
{
masterAndCommander.setImageCaption(new generic_callback(guiChangePhotoCaption_Callback), _currentAlbumUID, ((ComplexPhotoData)mainWindowAlbumList.SelectedItem).idInAlbum, caption);
}
}
/*
* Created By: Ryan Causey
* Created Date: 4/8/13
* Last Edited By:
* Last Edited Date:
*/
/// <summary>
/// Callback for guiChangePhotoCaption. Simply displays an error if there was one.
/// </summary>
/// <param name="error"></param>
public void guiChangePhotoCaption_Callback(ErrorReport error)
{
if (error.reportStatus == ReportStatus.FAILURE)
{
showErrorMessage(errorStrings.changeCommentFailure);
}
}
/**************************************************************************************************************************
* Author: Bill Sanders
* Created on: 4/7/13
**************************************************************************************************************************/
/// <summary>
/// Copies the selected photos to the background clipboard.
/// </summary>
private void guiCopySelectedPhotosToClipboard()
{
//make sure an item is selected
if (mainWindowAlbumList.SelectedItems != null)
{
// if the clipboard is currently empty, we're in copy-mode
ComplexPhotoData[] clipArray = new ComplexPhotoData[mainWindowAlbumList.SelectedItems.Count];
mainWindowAlbumList.SelectedItems.CopyTo(clipArray, 0);
_clipboardOfPhotos = clipArray.ToList();
_clipboardAlbumSrcID = _currentAlbumUID;
}
}
/**************************************************************************************************************************
* Author: Bill Sanders
* Created on: 4/7/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/7/13
**************************************************************************************************************************/
/// <summary>
/// Pastes the photos from the background clipboard to the selected album.
/// </summary>
private void guiPasteClipboardPhotosToAlbum()
{
// First check if the clipboard even has anything...
if (_clipboardOfPhotos.Count == 0)
{
// Nope, just ignore the action.
//showErrorMessage(errorStrings.failedToPasteImages);
return;
}
// So we have photos, where are we pasting them?
// Check if we're in library view or album view
Guid albumUID = _currentAlbumUID;
if (albumUID == Guid.Empty)
{
// library view
if (mainWindowAlbumList.SelectedItem == null)
{
//showErrorMessage(errorStrings.copyToClipboardWarning);
return;
}
albumUID = ((SimpleAlbumData)mainWindowAlbumList.SelectedItem).UID;
}
// Now that we have the album and a given set of pictures
// Tell the GUI we are importing
_isImporting = true;
//hide the addPhotosDockButton
addPhotosDockButton.Visibility = Visibility.Collapsed;
//show the cancel import dock button
//cancelPhotoImportDockButton.Visibility = Visibility.Visible;
//pass all the files names to a backend function call to start adding the files.
// sneakily reuse the guiImportPhotos_Callback....
masterAndCommander.addExistingImagesToAlbum(
new addNewPictures_callback(guiImportPhotos_Callback),
_clipboardOfPhotos,
albumUID);
// repopulate the list of albums, mostly to get the new thumbnail generated, if applicable.
populateAlbumView(true);
// empty the clipbaord.
_clipboardOfPhotos.Clear();
_clipboardAlbumSrcID = Guid.Empty;
}
/**************************************************************************************************************************
* Created By: Ryan Causey
* Created On: 4/3/13
* Last Edited By:
* Last Edited Date:
**************************************************************************************************************************/
/// <summary>
/// Deletes the selected album from the program.
/// </summary>
private void guiDeleteSelectedAlbum()
{
//make sure an item is selected
if (mainWindowAlbumList.SelectedItem != null)
{
SimpleAlbumData albumToDelete = (SimpleAlbumData)mainWindowAlbumList.SelectedItem;
// If we're deleting the album that has the clipboard images on it, clear the clipboard.
if ((_clipboardOfPhotos.Count > 0) && (albumToDelete.UID == _clipboardAlbumSrcID))
{
_clipboardOfPhotos.Clear();
_clipboardAlbumSrcID = Guid.Empty;
}
masterAndCommander.removeAlbum(new generic_callback(guiDeleteSelectedAlbum_Callback), albumToDelete.UID);
}
}
/**************************************************************************************************************************
* Created By: Ryan Causey
* Created On: 4/3/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/7/13
**************************************************************************************************************************/
/// <summary>
/// Callback for guiDeleteSelectedAlbum. If there is an error something really bad happened.
/// Notify the user, rebuild the database and consolidate all photographs into a single backup album.
/// </summary>
/// <param name="error">Error report from the back end.</param>
public void guiDeleteSelectedAlbum_Callback(ErrorReport error)
{
if (error.reportStatus == ReportStatus.FAILURE || error.reportStatus == ReportStatus.SUCCESS_WITH_WARNINGS)
{
//something really bad happened
//notify the user, rebuild the database and consolidate all photographs into a single backup album
//showErrorMessage(errorStrings.deleteAlbumFailure); //super temporary
masterAndCommander.rebuildBackendOnFilesystem(new generic_callback(rebuildBackend_Callback));
}
}
/**************************************************************************************************************************
* Created By: Ryan Causey
* Created On: 4/4/13
* Last Edited By:
* Last Edited Date:
**************************************************************************************************************************/
/// <summary>
/// GUI function to begin the transition to the album view from the library view.
/// </summary>
private void guiEnterAlbumView()
{
//make sure an item is selected
if (mainWindowAlbumList.SelectedItem != null)
{
SimpleAlbumData currentAlbumData = (SimpleAlbumData)mainWindowAlbumList.SelectedItem;
//call the backend to get all photos in this album.
_currentAlbumUID = currentAlbumData.UID;
// Set the app's titlebar to display the app name and the album name
this.appTitleBarLabel.Content = "PhotoBomber - " + currentAlbumData.albumName;
masterAndCommander.getAllImagesInAlbum(new getAllPhotosInAlbum_callback(guiEnterAlbumView_Callback), _currentAlbumUID);
}
}
/**************************************************************************************************************************
* Created By: Ryan Causey
* Created On: 4/5/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/7/13
**************************************************************************************************************************/
/// <summary>
/// Callback for guiEnterAlbumView. Takes the returned ReadOnlyObservableCollection and binds the listView to it
/// as well as swaps the data template.
/// </summary>
/// <param name="error">Error report from backend</param>
/// <param name="picturesInAlbum">Collection of photos in the album.</param>
public void guiEnterAlbumView_Callback(ErrorReport error, ReadOnlyObservableCollection<ComplexPhotoData> picturesInAlbum)
{
if (error.reportStatus == ReportStatus.FAILURE)
{
//show user an error message that retrieving the pictures did not work
showErrorMessage(errorStrings.getPhotosFailure);
}
else
{
//going into album
_isInsideAlbum = true;
if (error.reportStatus == ReportStatus.SUCCESS_WITH_WARNINGS)
{
//show the user a notification that some pictures are not displayed
showErrorMessage(errorStrings.getPhotosWarning);
}
//swap data templates and change bindings.
mainWindowAlbumList.ItemTemplate = this.Resources["ListItemTemplate"] as DataTemplate;
_listOfPhotos = picturesInAlbum;
mainWindowAlbumList.ItemsSource = _listOfPhotos;
_ImageListCollectionView = (CollectionView)CollectionViewSource.GetDefaultView(_listOfPhotos);
//change the selection mode to Extended
mainWindowAlbumList.SelectionMode = SelectionMode.Extended;
//show the return to library view button on the dock
libraryDockButton.Visibility = Visibility.Visible;
//show the addPhotos dock button if we are not running an import operation
if (!_isImporting)
{
addPhotosDockButton.Visibility = Visibility.Visible;
}
//hide the add new album button on the dock
addDockButton.Visibility = Visibility.Collapsed;
/* Commenting out these as we will swap whole context menu's!
//temporary fix to prevent an unhandled exception
viewMenuItemLibraryButton.Visibility = Visibility.Collapsed;
//hide the delete album button
deleteMenuItemLibraryButton.Visibility = Visibility.Collapsed;
//show the delete photo button
deleteMenuItemPhotoButton.Visibility = Visibility.Visible;
*/
if (mainWindowAlbumList.Items.IsEmpty == false)
{
mainWindowAlbumList.SelectedItem = mainWindowAlbumList.Items[0];
mainWindowAlbumList.Focus();
}
imageSortingButton.Visibility = Visibility.Visible;
ItemAddOrEditDialogBar.Visibility = Visibility.Collapsed;
}
}
/**************************************************************************************************************************
* Created By: Ryan Causey
* Created Date: 4/5/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/8/13
**************************************************************************************************************************/
/// <summary>
/// GUI function to transition back to the library view by changing the data template and item source.
/// </summary>
private void guiReturnToLibraryView()
{
mainWindowAlbumList.ItemTemplate = this.Resources["LibraryListItemFrontTemplate"] as DataTemplate;
//refresh the view to make sure we update with new album thumbnails
populateAlbumView(true);
// Set the titlebar back to the default: Appname and "my photo library!"
this.appTitleBarLabel.Content = Settings.AppTitleBarText;
mainWindowAlbumList.ItemsSource = _listOfAlbums;
//change the selection mode to single
mainWindowAlbumList.SelectionMode = SelectionMode.Single;
//collapse the go back button
libraryDockButton.Visibility = Visibility.Collapsed;
//collapse the addPhotos button
addPhotosDockButton.Visibility = Visibility.Collapsed;
//show the add album dock button
addDockButton.Visibility = Visibility.Visible;
/* Commenting out these as we will swap whole context menu's!
//temporary fix to prevent an unhandled exception
viewMenuItemLibraryButton.Visibility = Visibility.Visible;
//show the delete album button
deleteMenuItemLibraryButton.Visibility = Visibility.Visible;
//hide the delete photo button
deleteMenuItemPhotoButton.Visibility = Visibility.Collapsed;
*/
//hise the sorting button
imageSortingButton.Visibility = Visibility.Collapsed;
ItemAddOrEditDialogBar.Visibility = Visibility.Collapsed;
//close any open viewImage windows
if (_view != null)
{
_view.Close();
}
_currentAlbumUID = Guid.Empty;
//returning to libraryView
_isInsideAlbum = false;
if (mainWindowAlbumList.Items.IsEmpty == false)
{
mainWindowAlbumList.SelectedItem = mainWindowAlbumList.Items[0];
mainWindowAlbumList.Focus();
}
}
/**************************************************************************************************************************
* Created By: Ryan Causey
* Created Date: 4/5/13
* Last Edited By: Ryan Causey
* Last Edited Date: 4/7/13
**************************************************************************************************************************/
/// <summary>
/// GUI function that shows a file dialogue and then calls the back end to add the selected photographs
/// </summary>
private void guiImportPhotos()
{
OpenFileDialog photoDialogue = new OpenFileDialog();
//filter the file types available
photoDialogue.Filter = promptStrings.addFileDialogueFilter;
//set the intial directory to the my pictures directory
photoDialogue.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
//allow multiple photographs to be selected
photoDialogue.Multiselect = true;
//show the dialogue
Nullable<bool> openFilesResult = photoDialogue.ShowDialog();
//if the user selected files
if ((bool)openFilesResult)
{
//tell the GUI at large we are importing
_isImporting = true;
//hide the addPhotosDockButton
addPhotosDockButton.Visibility = Visibility.Collapsed;
//show the cancel import dock button
cancelPhotoImportDockButton.Visibility = Visibility.Visible;
//need to get the file extensions for the goddamned splicers
List<string> extensions = new List<string>();
//GODDAMNED SPLICERS!
foreach (String s in photoDialogue.FileNames)
{
extensions.Add(System.IO.Path.GetExtension(s));
}
//show the progress bar
progressBar.Visibility = Visibility.Visible;
progressBar.Minimum = 1;