// // Copyright (C) 2009 Jordi Mas i Hernandez, jmas@softcatala.org // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using Gtk; using Gdk; using System.Collections.Generic; using System.ComponentModel; using Mono.Unix; using Mistelix.Widgets; using Mistelix.DataModel; using Mistelix.Core; namespace Mistelix.Widgets { class WelcomeView : Gtk.HBox { // Used to report when a file has been open from the recent file list public delegate void ProjectOpenEventHandler (object sender, ProjectOpenEventHandlerEventArgs e); public class ProjectOpenEventHandlerEventArgs: EventArgs { string project; public ProjectOpenEventHandlerEventArgs (string project) { this.project = project; } public string Project { get { return project; } } } // Contains the list of recent projects class RecentProjectsTreeView : TreeView { ListStore tree_store; WelcomeView view; BackgroundWorker thumbnailing; bool empty; public RecentProjectsTreeView (WelcomeView view) { this.view = view; Model = tree_store = CreateStore (); RulesHint = true; AppendColumn (Catalog.GetString ("Project"), new CellRendererText (), "text", COL_NAME); AppendColumn (Catalog.GetString ("Last Accessed"), new CellRendererText (), "text", COL_DATE); AppendColumn (Catalog.GetString ("Thumbnail"), new CellRendererPixbuf (), "pixbuf", COL_PIXBUF); RowActivated += OnRowActivate; tree_store.SetSortFunc (0, new Gtk.TreeIterCompareFunc (SortByTime)); thumbnailing = new BackgroundWorker (); thumbnailing.DoWork += new DoWorkEventHandler (DoWork); PopulateRecentFiles (); } ListStore CreateStore () { // Image filename, date, Image, full filename, thumbnail_done return new ListStore (typeof (string), typeof (string), typeof (Gdk.Pixbuf) , typeof (RecentFile), typeof (bool)); } void OnRowActivate (object o, RowActivatedArgs args) { if (view.ProjectOpen == null) return; TreeIter iter; tree_store.GetIter (out iter, args.Path); RecentFile recent; if (tree_store.GetValue (iter, COL_OBJECT) == null) return; recent = (RecentFile) tree_store.GetValue (iter, COL_OBJECT); view.ProjectOpen (this, new ProjectOpenEventHandlerEventArgs (recent.filename)); } public void PopulateRecentFiles () { tree_store.Clear (); if (view.recent_files.Items.Count == 0) { tree_store.AppendValues (Catalog.GetString ("No recent projects"), "", null, null); empty = true; return; } empty = false; foreach (RecentFile recent in view.recent_files.Items) { FileInfo fi = new FileInfo (recent.filename); tree_store.AppendValues (fi.Name, recent.TimeSinceEdited, null, recent, false); } tree_store.SetSortColumnId (0, SortType.Descending); if (thumbnailing.IsBusy == false) thumbnailing.RunWorkerAsync (tree_store); } public void AddRecentFile (RecentFile recent) { if (empty == true) { empty = false; tree_store.Clear (); } FileInfo fi = new FileInfo (recent.filename); tree_store.AppendValues (fi.Name, recent.TimeSinceEdited, null, recent, false); tree_store.SetSortColumnId (0, SortType.Descending); if (thumbnailing.IsBusy == false) thumbnailing.RunWorkerAsync (tree_store); } public void UpdateRecentFile (RecentFile item) { tree_store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter) { RecentFile recent = (RecentFile) tree_store.GetValue (iter, COL_OBJECT); if (recent.filename == item.filename) { tree_store.SetValue (iter, COL_OBJECT, item); tree_store.SetValue (iter, COL_DATE, item.TimeSinceEdited); tree_store.SetValue (iter, COL_THUMBNAIL, false); return true; } return false; }); tree_store.SetSortColumnId (0, SortType.Descending); if (thumbnailing.IsBusy == false) thumbnailing.RunWorkerAsync (tree_store); } public void RemoveRecentFile (RecentFile item) { tree_store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter) { RecentFile recent = (RecentFile) tree_store.GetValue (iter, COL_OBJECT); if (recent.filename == item.filename) { tree_store.Remove (ref iter); return true; } return false; }); } int SortByTime (Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) { RecentFile recent_a, recent_b; if (model.GetValue (a, COL_OBJECT) == null || model.GetValue (b, COL_OBJECT) == null) return 0; recent_a = (RecentFile) model.GetValue (a, COL_OBJECT); recent_b = (RecentFile) model.GetValue (b, COL_OBJECT); return DateTime.Compare (recent_a.timestamp, recent_b.timestamp); } static void DoWork (object sender, DoWorkEventArgs e) { ListStore store = (ListStore) e.Argument; Logger.Debug ("WelcomeView.DoWork. Start"); store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter) { RecentFile recent; Gdk.Pixbuf im; Project project; if (store.GetValue (iter, COL_OBJECT) == null) return false; if (((bool) store.GetValue (iter, COL_THUMBNAIL)) == true) return false; recent = (RecentFile) store.GetValue (iter, COL_OBJECT); try { project = new Project (); project.Load (recent.filename); im = project.GetThumbnail (ThumbnailSizeManager.Current.Width, ThumbnailSizeManager.Current.Height); Logger.Debug ("WelcomeView.DoWork. Thumbnailed {0}", recent.filename); } catch (Exception ex) { Logger.Error ("WelcomeView.Dowork. Exception: " + ex.Message); return false; } Application.Invoke (delegate { if (im != null) store.SetValue (iter, COL_PIXBUF, im); store.SetValue (iter, COL_THUMBNAIL, true); } ); return false; }); Logger.Debug ("WelcomeView.DoWork. End"); } } Gtk.VBox action_vbox; Gtk.Label welcome_label; Gtk.Table action_table; Gtk.Button dvd_button; Gtk.Button slideshow_button; Gtk.VBox dvd_vbox; Gtk.Label recent_label; RecentProjectsTreeView recent_treeview; Gtk.Button buttonCancel; Gtk.Button buttonOk; RecentFilesStorage recent_files; const int COL_NAME = 0; const int COL_DATE = 1; const int COL_PIXBUF = 2; const int COL_OBJECT = 3; const int COL_THUMBNAIL = 4; const int BUTTON_SIZE = 80; public ProjectOpenEventHandler ProjectOpen; public EventHandler ButtonDVD; public EventHandler ButtonSlideshow; public WelcomeView (Gtk.VBox box, RecentFilesStorage recent_files) { string text; this.recent_files = recent_files; this.recent_files.ListUpdated += new ObservableList .CollectionChangedEventHandler (OnListUpdated); Homogeneous = true; Spacing = 6; BorderWidth = 20; // action_vbox packs all the elements in the left column action_vbox = new Gtk.VBox(); action_vbox.Spacing = 30; // Welcome label welcome_label = new Gtk.Label (); text = Catalog.GetString ("Welcome to Mistelix"); text += "\n\n"; text += Catalog.GetString ("Mistelix is a DVD authoring application also\nwith Theora slideshow creation capabilities."); welcome_label.Markup = text; action_vbox.Add (welcome_label); Gtk.Box.BoxChild w2 = ((Gtk.Box.BoxChild)(action_vbox[welcome_label])); w2.Position = 0; w2.Expand = false; w2.Fill = false; // Action table action_table = new Gtk.Table (((uint)(2)), ((uint)(1)), false); action_table.RowSpacing = ((uint)(50)); action_table.ColumnSpacing = ((uint)(1)); // DVD button dvd_button = new Gtk.Button (); dvd_button.CanFocus = true; dvd_button.UseUnderline = true; dvd_button.Clicked += new EventHandler (OnButtonDVD); Gtk.Alignment w3 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F); Gtk.HBox w4 = new Gtk.HBox (); w4.Spacing = 2; Gtk.Image w5 = new Gtk.Image(); Pixbuf pb = new Pixbuf (null, "button-dvd.svg"); w5.Pixbuf = pb.ScaleSimple (BUTTON_SIZE, BUTTON_SIZE, InterpType.Hyper); w4.Add (w5); Gtk.Label w7 = new Gtk.Label (); text = Catalog.GetString ("Create a DVD project"); text += "\n\n"; text += Catalog.GetString ("Create a DVD with videos and slideshows\nthat can be played in DVD players."); w7.LabelProp = text; w7.UseUnderline = true; w4.Add (w7); w3.Add (w4); dvd_button.Add (w3); action_table.Add (dvd_button); Gtk.Table.TableChild w11 = ((Gtk.Table.TableChild)(action_table[dvd_button])); w11.TopAttach = ((uint)(1)); w11.BottomAttach = ((uint)(2)); w11.XOptions = ((Gtk.AttachOptions)(4)); w11.YOptions = ((Gtk.AttachOptions)(4)); // Slideshown button slideshow_button = new Gtk.Button (); slideshow_button.CanFocus = true; slideshow_button.UseUnderline = true; slideshow_button.Clicked += new EventHandler (OnButtonSlideshow); Gtk.Alignment w12 = new Gtk.Alignment (0.5F, 0.5F, 0F, 0F); Gtk.HBox w13 = new Gtk.HBox (); w13.Spacing = 2; Gtk.Image w14 = new Gtk.Image (); pb = new Pixbuf (null, "button-slideshow.svg"); w14.Pixbuf = pb.ScaleSimple (BUTTON_SIZE, BUTTON_SIZE, InterpType.Hyper); w13.Add(w14); // Container child GtkHBox.Gtk.Container+ContainerChild Gtk.Label w16 = new Gtk.Label (); text = Catalog.GetString ("Create a Slideshow"); text += "\n\n"; text += Catalog.GetString ("Slideshow from a collection of images\nthat can be played in a PC."); w16.LabelProp = text; w16.UseUnderline = true; w13.Add (w16); w12.Add (w13); slideshow_button.Add (w12); action_table.Add(slideshow_button); Gtk.Table.TableChild w20 = ((Gtk.Table.TableChild)(action_table[slideshow_button])); w20.XOptions = ((Gtk.AttachOptions)(4)); w20.YOptions = ((Gtk.AttachOptions)(4)); action_vbox.Add(action_table); Gtk.Box.BoxChild w21 = ((Gtk.Box.BoxChild)(action_vbox[action_table])); w21.Position = 1; w21.Expand = false; w21.Fill = false; Add (action_vbox); Gtk.Box.BoxChild w22 = (Gtk.Box.BoxChild) this[action_vbox]; w22.Position = 0; w22.Expand = false; w22.Fill = false; // dvd_vbox packs all the elements in the left column dvd_vbox = new Gtk.VBox (); dvd_vbox.Spacing = 30; // Container child dvd_vbox.Gtk.Box+BoxChild recent_label = new Gtk.Label (); recent_label.Markup = Mono.Unix.Catalog.GetString ("Recent Projects"); dvd_vbox.Add(recent_label); Gtk.Box.BoxChild w23 = ((Gtk.Box.BoxChild)(dvd_vbox[recent_label])); w23.Position = 0; w23.Expand = false; w23.Fill = false; // Recent projects Treeview Gtk.ScrolledWindow scrolled_win = new Gtk.ScrolledWindow (); Gtk.VBox tree_vbox = new Gtk.VBox (); recent_treeview = new RecentProjectsTreeView (this); tree_vbox.Add (recent_treeview); scrolled_win.AddWithViewport (tree_vbox); dvd_vbox.Add (scrolled_win); Add (dvd_vbox); Gtk.Box.BoxChild treeview_child = ((Gtk.Box.BoxChild)(tree_vbox [recent_treeview])); treeview_child.Position = 1; treeview_child.Expand = false; treeview_child.Fill = false; Gtk.Box.BoxChild scrolled_child = ((Gtk.Box.BoxChild)(dvd_vbox [scrolled_win])); scrolled_child.Position = 1; scrolled_child.Expand = true; scrolled_child.Fill = true; Gtk.Box.BoxChild dvd_vbox_child = (Gtk.Box.BoxChild) this [dvd_vbox]; dvd_vbox_child.Position = 1; dvd_vbox_child.Expand = false; dvd_vbox_child.Fill = true; box.Add(this); } void OnButtonDVD (object sender, EventArgs args) { if (ButtonDVD != null) ButtonDVD (sender, args); } void OnButtonSlideshow (object sender, EventArgs args) { if (ButtonSlideshow != null) ButtonSlideshow (sender, args); } void OnListUpdated (object sender, ObservableList .CollectionChangedEventArgs e) { Logger.Debug ("WelcomeView.OnListUpdated. type:{0} item:s{1}", e.Type, e.Item); switch (e.Type) { case ObservableList.ChangeType.ElementChanged: recent_treeview.UpdateRecentFile (e.Item); break; case ObservableList.ChangeType.ElementAdded: recent_treeview.AddRecentFile (e.Item); break; case ObservableList.ChangeType.ElementRemoved: recent_treeview.RemoveRecentFile (e.Item); break; case ObservableList.ChangeType.ListCleared: recent_treeview.PopulateRecentFiles (); break; default: break; } } } }