/// <summary> /// Adds a new file entry to the list /// </summary> /// <param name="filePath">path of the file to add</param> /// <param name="thumbnailPath">path of the thumbnail file</param> /// <param name="dimensions">dimensions of the file</param> public void AddFile(string filePath, string thumbnailPath, string dimensions) { string thumb = thumbnailPath.ToLower(); if (!this.IsSupportedFileType(thumbnailPath)) { thumbnailPath = filePath; } string file = filePath.ToLower(); if (this.IsSupportedFileType(file)) { WallpaperEntry entry = this.GetEntry(filePath); if (entry == null) { entry = new WallpaperEntry(filePath, thumbnailPath, dimensions); this.map[filePath] = entry; if (this.sorted) { this.AddSortedToList(entry); } else { this.list.Add(entry); this.lastInsertIndex = this.list.Count - 1; } } } }
/// <summary> /// Handler for delete context menu item /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void FileList_DeleteFile(object sender, RoutedEventArgs args) { WallpaperEntry item = c_filelist.SelectedItem as WallpaperEntry; if (c_filelist.SelectedItem == null) { return; } this.activeList.RemoveFile(item.FilePath, true); if (this.activeList.Count > 0) { c_imagenext.IsEnabled = true; } else { c_imagenext.IsEnabled = false; } try { this.activeList.SaveToFile(); } catch (Exception ex) { ErrorLog.Log("Failed to the save the list file, it will continue to be updated in memory", ex); } }
/// <summary> /// Gets the path of a local copy of the file. /// If the file is online, it downloads to a cache and returns path of the local copy /// </summary> /// <param name="entry">entry of the file to lookup</param> /// <param name="isThumbnail">whether this is a thumbnail image</param> /// <returns>Path of the local copy</returns> /// <exception cref="Exception">Can throw exception</exception> private string GetLocalCopyOfImage(WallpaperEntry entry, bool isThumbnail) { if (isThumbnail && Settings.Instance.HighResolutionThumbs) { isThumbnail = false; } return(GetLocalCopyOfImage(isThumbnail ? entry.ThumbnailPath : entry.FilePath, isThumbnail)); }
/// <summary> /// Look for an entry based on the file path /// </summary> /// <param name="file">path of the file to search</param> /// <returns></returns> public WallpaperEntry GetEntry(string file) { WallpaperEntry entry = null; if (this.map.TryGetValue(file, out entry)) { return(entry); } return(null); }
/// <summary> /// Handler for set presentation button /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void PresentationSet_Click(object sender, RoutedEventArgs args) { if (Settings.Instance.InPresentationMode) { return; } WallpaperEntry item = c_filelist.SelectedItem as WallpaperEntry; if (item != null) { Settings.Instance.PresentationImage = item.FilePath; this.UpdatePresentationMode(false); } }
/// <summary> /// Removes a file entry from the list /// </summary> /// <param name="filePath">path of the file to remove</param> /// <param name="delete">indicates whether the file should be deleted as well</param> public void RemoveFile(string filePath, bool delete) { WallpaperEntry entry = null; if (this.map.TryGetValue(filePath, out entry)) { this.map.Remove(filePath); this.list.Remove(entry); this.lastInsertIndex = -1; if (delete && File.Exists(filePath)) { FileSystem.DeleteFile(filePath, UIOption.AllDialogs, RecycleOption.SendToRecycleBin, UICancelOption.DoNothing); } } }
/// <summary> /// Handler for open context menu item /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void FileList_OpenFile(object sender, RoutedEventArgs args) { if (c_filelist.SelectedItem == null) { return; } try { WallpaperEntry item = c_filelist.SelectedItem as WallpaperEntry; Process.Start("explorer.exe", item.FilePath); } catch (Exception e) { ErrorLog.Log("Open file failed.", e); } }
/// <summary> /// Handler for copy path context menu item /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void FileList_CopyPath(object sender, RoutedEventArgs args) { if (c_filelist.SelectedItem == null) { return; } try { WallpaperEntry item = c_filelist.SelectedItem as WallpaperEntry; System.Windows.Clipboard.SetText(item.FilePath); } catch (Exception e) { ErrorLog.Log("Copy to clipboard failed.", e); } }
/// <summary> /// Set the provided image as the background /// </summary> /// <param name="entry">the image entry</param> private void SetBackgroundImage(WallpaperEntry entry) { try { // try to download image to cache string localFile = this.GetLocalCopyOfImage(entry, false); if (localFile == null) { throw new Exception("Could not get local copy of the image"); } // set the new file as the desktop wallpaper BackgroundSetter.SetBackgroundImage(localFile, Settings.Instance.DisplayMode, Settings.Instance.GetBackgroundColor()); } catch (Exception e) { throw new Exception("Setting image did not complete fully", e); } Settings.Instance.SelectedImage = entry.FilePath; this.trayIcon.SetToolText(entry.FilePath); }
/// <summary> /// Set the current selection as the background image /// </summary> public void SetCurrentImageAsBackground() { // re-entrant protection if (this.BeginTransaction()) { return; } WallpaperEntry entry = c_filelist.SelectedItem as WallpaperEntry; // try to set the background try { this.SetBackgroundImage(entry); } catch (Exception e) { ErrorLog.Log("Could not set the current image as the background, please choose a different image.", e); } this.EndTransaction(); }
/// <summary> /// Add an entry to the list in a sorted manner /// </summary> /// <param name="newEntry">the entry to add</param> private void AddSortedToList(WallpaperEntry newEntry) { if (this.lastInsertIndex >= this.list.Count) { this.lastInsertIndex = -1; } if (this.lastInsertIndex == -1) { foreach (WallpaperEntry entry in this.list) { if (entry.FilePath.CompareTo(newEntry.FilePath) > 0) { int index = this.list.IndexOf(entry); this.list.Insert(index, newEntry); this.lastInsertIndex = index; return; } } this.list.Add(newEntry); this.lastInsertIndex = this.list.Count - 1; return; } else { int currentIndex = this.lastInsertIndex; WallpaperEntry lastAddedItem = this.list[this.lastInsertIndex]; if (lastAddedItem.FilePath.CompareTo(newEntry.FilePath) > 0) { //go down in list currentIndex--; while (currentIndex > 0) { WallpaperEntry current = this.list[currentIndex]; if (current.FilePath.CompareTo(newEntry.FilePath) <= 0) { this.list.Insert(currentIndex + 1, newEntry); this.lastInsertIndex = currentIndex + 1; return; } currentIndex--; } this.list.Insert(0, newEntry); this.lastInsertIndex = 0; return; } else { //go up in list currentIndex++; while (currentIndex < this.list.Count) { WallpaperEntry current = this.list[currentIndex]; if (current.FilePath.CompareTo(newEntry.FilePath) > 0) { this.list.Insert(currentIndex, newEntry); this.lastInsertIndex = currentIndex; return; } currentIndex++; } this.list.Add(newEntry); this.lastInsertIndex = this.list.Count - 1; return; } } }
/// <summary> /// Load the list from file /// </summary> /// <exception cref="Exception">Can throw exception</exception> public void LoadFromFile() { XmlTextReader reader = null; this.RemoveAll(); try { //the list file doesn't exist, this might be the first time the application ran if (!File.Exists(this.path)) { this.map.Clear(); this.list.Clear(); return; } reader = new XmlTextReader(this.path); reader.WhitespaceHandling = WhitespaceHandling.None; reader.MoveToContent(); if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "List")) { //read to the first element if (reader.Read()) { while (true) { if ((reader.NodeType == XmlNodeType.EndElement) && (reader.Name == "List")) { break; } string filePath = reader.ReadElementString("FilePath"); if (!string.IsNullOrEmpty(filePath)) { string thumbnailPath = reader.ReadElementString("ThumbnailPath"); if (string.IsNullOrEmpty(thumbnailPath)) { thumbnailPath = filePath; } string dimensions = reader.ReadElementString("Dimensions"); WallpaperEntry entry = new WallpaperEntry(filePath, thumbnailPath, dimensions); this.map[filePath] = entry; this.list.Add(entry); } } } else { //list is empty. Nothing to do } } else { throw new Exception("Invalid starting token"); } } finally { if (reader != null) { reader.Close(); } } }
/// <summary> /// Look for the previous valid image /// </summary> /// <param name="setImage">whether to set the previous valid image as the background</param> public async void GotoPreviousImage(bool setImage) { // re-entrant protection if (this.BeginTransaction()) { return; } // if the image also needs to be set then show balloon tooltip as it can be a lengthy process if (setImage) { this.trayIcon.SetLoadingText(); } bool listUpdated = false; WallpaperEntry newEntry = null; c_filelist.SelectedIndex = -1; // we will keep looping till we find a valid image while (true) { await Task.Delay(1); // get the index of the previous image if (this.imageStack.Count == 0) { newEntry = null; } else { this.imageStack.Pop(); if (this.imageStack.Count > 0) { newEntry = this.imageStack.First(); } } if (this.imageStack.Count > 1) { c_imageprevious.IsEnabled = true; } else { c_imageprevious.IsEnabled = false; } // if no previous entry, break the loop if (newEntry == null) { break; } // try to load the thumbnail try { string filePath = this.GetLocalCopyOfImage(newEntry, true); BitmapDecoder uriBitmap = BitmapDecoder.Create(new Uri(filePath), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } catch (Exception) { // in case of an exception remove the entry from the list this.activeList.RemoveFile(newEntry.FilePath, true); listUpdated = true; // try a different image continue; } if (setImage) { // try to set the background try { this.SetBackgroundImage(newEntry); } catch (Exception) { // in case of an exception remove the entry from the list this.activeList.RemoveFile(newEntry.FilePath, true); listUpdated = true; // try a different image continue; } } // if the current selection succeeded to load, end the loop break; } if (listUpdated) { if (this.activeList.Count > 0) { c_imagenext.IsEnabled = true; } else { c_imagenext.IsEnabled = false; } try { this.activeList.SaveToFile(); } catch (Exception) { // nothing to do here } } this.EndTransaction(); // set the appropriate image as current if (newEntry == null) { c_filelist.SelectedIndex = -1; } else { c_filelist.SelectedItem = newEntry; } }
/// <summary> /// Constructor for the main window /// </summary> public MainWindow() { // check for an update GenericUpdater.Updater.DoUpdate("WallpaperManager", MainWindow.Version, "WallpaperManager_Version.xml", "WallpaperManager.msi", new GenericUpdater.Updater.UpdateFiredDelegate(UpdateFired)); // load the settings Settings settings = Settings.Instance; InitializeComponent(); // hide the settings panel c_settings.ShowPanel(false); // setup the tray icon this.trayIcon = new TrayIcon(this); this.imageStack = new Stack <WallpaperEntry>(); c_imagenext.IsEnabled = false; c_imageprevious.IsEnabled = false; c_imageset.IsEnabled = false; // setup the file list c_tabs.SelectedIndex = Settings.Instance.FileListIndex; // start the auto change time if required this.autoChangeTimer = new Timer(); SetupAutoChangeTimer(); // show the tray icon this.trayIcon.UpdateTrayIcon(true); // hide the main window if required this.trayIcon.UpdateMainWindow(!Settings.Instance.StartMinimized); // setup the presentation mode this.UpdatePresentationMode(Settings.Instance.InPresentationMode); // select the appropriate image if (Settings.Instance.InPresentationMode) { this.trayIcon.SetToolText(Settings.Instance.PresentationImage); WallpaperEntry entry = this.activeList.GetEntry(Settings.Instance.SelectedImage); if (entry != null) { c_filelist.SelectedItem = entry; } } else { if (Settings.Instance.ChangeAtStartup) { this.GotoNextImage(true); } else { this.trayIcon.SetToolText(Settings.Instance.SelectedImage); WallpaperEntry entry = this.activeList.GetEntry(Settings.Instance.SelectedImage); if (entry != null) { c_filelist.SelectedItem = entry; } } } }
/// <summary> /// Look for the next valid image /// </summary> /// <param name="setImage">whether to set the next valid image as the background</param> /// <param name="startIndex">the index to start the scan from, if this is null use the current index</param> public async void GotoNextImage(bool setImage, int?startIndex = null) { // re-entrant protection if (this.BeginTransaction()) { return; } // if the image also needs to be set then show balloon tooltip as it can be a lengthy process if (setImage) { this.trayIcon.SetLoadingText(); } bool listUpdated = false; int currentIndex = (startIndex.HasValue) ? startIndex.Value : c_filelist.SelectedIndex; c_filelist.SelectedIndex = -1; int newIndex = -1; // we will keep looping till we find a valid image while (true) { await Task.Delay(1); // get the index of the next image if (this.activeList.Count == 0) { newIndex = -1; break; } else if (Settings.Instance.ChangeRandomly) { Random rand = new Random(); while (true) { int index = rand.Next(this.activeList.Count); if (index != currentIndex) { newIndex = index; break; } } } else { if (currentIndex == -1) { newIndex = 0; } else if (currentIndex >= (this.activeList.Count - 1)) { newIndex = 0; } else { newIndex = currentIndex + 1; } } // get the entry corresponding to the index WallpaperEntry newEntry = this.activeList.List[newIndex]; // try to load the thumbnail try { string filePath = this.GetLocalCopyOfImage(newEntry, true); BitmapDecoder uriBitmap = BitmapDecoder.Create(new Uri(filePath), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } catch (Exception) { // in case of an exception remove the entry from the list this.activeList.RemoveFile(newEntry.FilePath, true); listUpdated = true; // try a different image continue; } if (setImage) { // try to set the background try { this.SetBackgroundImage(newEntry); } catch (Exception) { // in case of an exception remove the entry from the list this.activeList.RemoveFile(newEntry.FilePath, true); listUpdated = true; // try a different image continue; } } // if the current selection succeeded to load, end the loop break; } if (listUpdated) { if (this.activeList.Count > 0) { c_imagenext.IsEnabled = true; } else { c_imagenext.IsEnabled = false; } try { this.activeList.SaveToFile(); } catch (Exception) { // nothing to do here } } this.EndTransaction(); // set the appropriate image as current c_filelist.SelectedIndex = newIndex; }
/// <summary> /// Set the UI properties based on the current image /// </summary> public async void GotoCurrentImage() { WallpaperEntry currentItem = c_filelist.SelectedItem as WallpaperEntry; if (currentItem == null) { // if no current entry found, clear out the UI c_imageset.IsEnabled = false; c_previewimage.Source = null; c_imageresolution.Text = string.Empty; c_imageformat.Text = string.Empty; c_imagefilesize.Text = string.Empty; if (this.imageStack.Count > 1) { c_imageprevious.IsEnabled = true; } else { c_imageprevious.IsEnabled = false; } c_filelist.ScrollIntoView(c_filelist.SelectedItem); } else { // try setting the UI properties based on current selection if (this.BeginTransaction()) { return; } c_imageset.IsEnabled = true; try { // download the file to the cache if required string filePath = this.GetLocalCopyOfImage(currentItem, true); // load the image in memory BitmapDecoder uriBitmap = BitmapDecoder.Create(new Uri(filePath), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); // set the image in UI c_previewimage.Source = uriBitmap.Frames[0]; // update the image info c_imageformat.Text = uriBitmap.CodecInfo.FriendlyName; if (String.IsNullOrEmpty(currentItem.Dimensions)) { currentItem.Dimensions = uriBitmap.Frames[0].PixelWidth.ToString() + "x" + uriBitmap.Frames[0].PixelHeight.ToString(); } c_imageresolution.Text = currentItem.Dimensions; FileInfo info = new FileInfo(filePath); c_imagefilesize.Text = info.Length.ToString() + " bytes"; // push the current image in the stack if ((this.imageStack.Count == 0) || (currentItem != this.imageStack.First())) { this.imageStack.Push(currentItem); } // enable the 'previous' button if there is something in the stack if (this.imageStack.Count > 1) { c_imageprevious.IsEnabled = true; } else { c_imageprevious.IsEnabled = false; } // scroll the selection into view c_filelist.ScrollIntoView(c_filelist.SelectedItem); this.EndTransaction(); // completed processed current selection return; } catch (Exception) { // nothing to do here } // we should come here only if something went wrong in processing current selection // in that case store the current index and eset the position int currentIndex = c_filelist.SelectedIndex; c_filelist.SelectedIndex = -1; // remove the bad entry from the list this.activeList.RemoveFile(currentItem.FilePath, true); if (this.activeList.Count > 0) { c_imagenext.IsEnabled = true; } else { c_imagenext.IsEnabled = false; } try { this.activeList.SaveToFile(); } catch (Exception) { // nothing to do here } this.EndTransaction(); // now look for the next best alternative await Task.Delay(1); this.GotoNextImage(false, currentIndex - 1); } }