Added the table for viewing/paging commits.
[Gitrdone.git] / Form1.cs
blob9dd921a94be285320608fff607e5939f49860008
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Text;
7 using System.Windows.Forms;
8 using System.Diagnostics;
9 using System.IO;
10 using Git;
12 namespace Gitrdone
14 public partial class Form1 : Form
16 protected List<Git.File> m_files;
17 protected OutputTextWriter m_outputWriter;
18 Prefs m_prefs = new Prefs();
19 Repo m_currentRepo;
20 ImageList m_imageList = new ImageList();
21 TreeNode m_rootNode;
22 protected Dictionary<string, string> m_expandedPaths = new Dictionary<string, string>();
23 protected int m_selectedTypes = -1;
24 protected Commit m_lastCommitInPage;
25 protected Stack<Commit> m_topCommits = new Stack<Commit>();
27 public Form1()
29 InitializeComponent();
30 //TextWriter stdout = System.Console.Out;
31 //OutputTextWriter m_outputWriter = new OutputTextWriter(m_outputArea, stdout);
32 //System.Console.SetOut(m_outputWriter);
33 m_workspaceTree.BeforeExpand += new TreeViewCancelEventHandler(OnBeforeExpand);
34 m_workspaceTree.AfterCollapse += new TreeViewEventHandler(OnAfterCollapse);
35 Executioner.BinaryDirPath = m_prefs.GitDir;
36 SetReposList();
37 PopulateImageList();
38 m_workspaceTree.ImageList = m_imageList;
39 m_workspaceTree.TreeViewNodeSorter = new Gitrdone.NodeSorter();
40 m_workspaceTree.FullRowSelect = true;
41 m_workspaceTree.AfterSelect += new TreeViewEventHandler(OnNodeSelected);
44 void OnNodeSelected(object sender, TreeViewEventArgs e)
46 EnableModifyButtons(m_workspaceTree.SelectedNode != null);
49 protected void EnableModifyButtons(bool bEnable)
51 m_addFileButton.Enabled = bEnable;
52 m_removeFiles.Enabled = bEnable;
53 m_revertFiles.Enabled = bEnable;
56 void OnAfterCollapse(object sender, TreeViewEventArgs e)
58 if (Enabled)
60 m_expandedPaths.Remove((string)e.Node.Tag);
64 void OnBeforeExpand(object sender, TreeViewCancelEventArgs e)
66 m_workspaceTree.SelectedNode = e.Node;
67 if (Enabled && !m_expandedPaths.ContainsKey((string)e.Node.Tag))
69 m_expandedPaths.Add((string)e.Node.Tag, null);
73 private void PopulateImageList()
75 System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
76 System.Resources.ResourceManager m = new System.Resources.ResourceManager("Gitrdone.Properties.Resources", a);
77 Image im = (System.Drawing.Image)m.GetObject("folder");
78 m_imageList.Images.Add("folder", im);
80 im = (System.Drawing.Image)m.GetObject("page");
81 m_imageList.Images.Add("normal", im);
82 im = (System.Drawing.Image)m.GetObject("page_edit");
83 m_imageList.Images.Add("modified", im);
84 im = (System.Drawing.Image)m.GetObject("page_add");
85 m_imageList.Images.Add("added", im);
86 im = (System.Drawing.Image)m.GetObject("page_delete");
87 m_imageList.Images.Add("delete", im);
88 im = (System.Drawing.Image)m.GetObject("page_error");
89 m_imageList.Images.Add("unmerged", im);
90 im = (System.Drawing.Image)m.GetObject("disconnect");
91 m_imageList.Images.Add("unknown", im);
93 im = (System.Drawing.Image)m.GetObject("page_error");
94 m_imageList.Images.Add("broken", im);
95 im = (System.Drawing.Image)m.GetObject("page_lightning");
96 m_imageList.Images.Add("modechanged", im);
97 im = (System.Drawing.Image)m.GetObject("page_copy");
98 m_imageList.Images.Add("copied", im);
99 im = (System.Drawing.Image)m.GetObject("page_go");
100 m_imageList.Images.Add("renamed", im);
103 bool SetReposList()
105 if (m_prefs.Repos == null)
107 m_prefs.Repos = new System.Collections.Specialized.StringCollection();
109 object o = m_reposCombo.SelectedItem;
110 m_reposCombo.Items.Clear();
111 foreach (string s in m_prefs.Repos)
113 m_reposCombo.Items.Add(s);
115 m_reposCombo.SelectedItem = o;
116 return true;
119 void PreferencesUpdated()
121 Executioner.BinaryDirPath = m_prefs.GitDir;
122 SetReposList();
125 protected bool UpdateTags()
127 return true;
130 protected bool UpdateBranches()
132 m_branchesCombo.Items.Clear();
133 foreach (Branch b in m_currentRepo.Branches)
135 m_branchesCombo.Items.Add(b.Name);
137 m_branchesCombo.SelectedItem = m_currentRepo.CurrentBranch.Name;
138 return true;
141 protected void SetNodeImage(TreeNode n, Git.File f)
143 switch (f.State)
145 case FileState.Normal:
146 n.ImageKey = "normal";
147 n.SelectedImageKey = "normal";
148 break;
149 case FileState.Deleted:
150 n.ImageKey = "delete";
151 n.SelectedImageKey = "delete";
152 break;
153 case FileState.Modified:
154 n.ImageKey = "modified";
155 n.SelectedImageKey = "modified";
156 break;
157 case FileState.Unknown:
158 n.ImageKey = "unknown";
159 n.SelectedImageKey = "unknown";
160 break;
161 case FileState.Unmerged:
162 n.ImageKey = "unmerged";
163 n.SelectedImageKey = "unmerged";
164 break;
165 case FileState.Added:
166 n.ImageKey = "added";
167 n.SelectedImageKey = "added";
168 break;
169 case FileState.Copied:
170 n.ImageKey = "copied";
171 n.SelectedImageKey = "copied";
172 break;
173 case FileState.ModeChanged:
174 n.ImageKey = "modechanged";
175 n.SelectedImageKey = "modechanged";
176 break;
177 case FileState.Broken:
178 n.ImageKey = "broken";
179 n.SelectedImageKey = "broken";
180 break;
181 case FileState.Renamed:
182 n.ImageKey = "renamed";
183 n.SelectedImageKey = "renamed";
184 break;
185 default:
186 n.ImageKey = "unknown";
187 n.SelectedImageKey = "unknown";
188 break;
192 protected void AddNewFileNode(TreeNode n, Git.File f)
194 TreeNode subNode = n.Nodes.Add(f.Name, f.Name);
195 subNode.Tag = f;
196 SetNodeImage(subNode, f);
199 protected TreeNode AddNewDirNode(TreeNode n, string subpath, string tag)
201 TreeNode subNode = n.Nodes.Add(subpath, subpath);
202 subNode.ImageIndex = 0;
203 subNode.Tag = tag;
204 return subNode;
207 protected TreeNode BuildTreePath(string path)
209 string[] parts = path.Split(Repo.DirectorySeparator.ToCharArray());
210 TreeNode currentNode = m_rootNode;
211 foreach (string part in parts)
213 int idx = currentNode.Nodes.IndexOfKey(part);
214 if (idx > -1)
216 currentNode = currentNode.Nodes[idx];
218 else
220 currentNode = AddNewDirNode(currentNode, part, path);
223 return currentNode;
226 protected bool ResetRepoTree(Repo repo)
228 this.Enabled = false;
229 m_files = repo.ListFiles();
230 System.Console.WriteLine("files: " + m_files.Count);
231 System.Collections.IComparer sorter = m_workspaceTree.TreeViewNodeSorter;
232 m_workspaceTree.TreeViewNodeSorter = null;
233 m_workspaceTree.BeginUpdate();
234 m_workspaceTree.Nodes.Clear();
235 m_rootNode = new TreeNode("root");
236 m_rootNode.Tag = "";
237 m_rootNode.ImageIndex = 0;
238 m_workspaceTree.Nodes.Add(m_rootNode);
239 Multidict<string, Git.File> dict = new Multidict<string, Git.File>();
240 foreach (Git.File f in m_files)
242 if (0 != ((int)f.State & m_selectedTypes))
244 dict.Add(f.RelativePath, f);
247 foreach (KeyValuePair<string, List<Git.File>> pair in dict)
249 TreeNode nodeToUse = m_rootNode;
250 if (pair.Key != "")
252 nodeToUse = BuildTreePath(pair.Key);
254 foreach (Git.File f in pair.Value)
256 AddNewFileNode(nodeToUse, f);
259 m_workspaceTree.TreeViewNodeSorter = sorter;
260 m_workspaceTree.EndUpdate();
261 this.Enabled = true;
262 return true;
265 private void OnPreferencesClicked(object sender, EventArgs e)
267 PreferencesEditor p = new PreferencesEditor(m_prefs);
268 p.ShowDialog();
269 PreferencesUpdated();
272 private void OnManageRepos(object sender, EventArgs e)
274 RepoManager m = new RepoManager(m_prefs);
275 m.ShowDialog();
276 SetReposList();
279 private void OnRepoChanged(object sender, EventArgs e)
281 m_expandedPaths.Clear();
282 if (m_reposCombo.SelectedIndex > -1)
284 m_currentRepo = new Repo(m_reposCombo.SelectedItem.ToString());
285 if (! (ResetRepoTree(m_currentRepo) &&
286 UpdateBranches() && UpdateTags()) )
288 MessageBox.Show("There was an error switching to the repo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
290 m_fetchCommits.Enabled = true;
291 m_treeStrip.Enabled = true;
292 m_commitsView.Items.Clear();
293 m_previousCommits.Enabled = false;
294 m_nextCommits.Enabled = false;
295 m_topCommits.Clear();
296 m_lastCommitInPage = null;
298 else
300 MessageBox.Show("Select a repo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
304 private void OnBranchChanged(object sender, EventArgs e)
306 if (m_branchesCombo.SelectedIndex > -1)
308 if (m_currentRepo.CurrentBranch.Name != m_branchesCombo.SelectedItem.ToString())
310 foreach (Branch b in m_currentRepo.Branches)
312 if (b.Name == m_branchesCombo.SelectedItem.ToString())
314 m_currentRepo.Checkout(b);
317 ResetRepoTree(m_currentRepo);
320 else
322 MessageBox.Show("Select a branch.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
326 private void OnCreateBranch(object sender, EventArgs e)
331 private void OnMergeBranch(object sender, EventArgs e)
336 private void OnDeleteBranch(object sender, EventArgs e)
341 private void OnExit(object sender, EventArgs e)
346 private void OnShowNormal(object sender, EventArgs e)
348 if (((ToolStripButton)sender).Checked)
350 m_selectedTypes = m_selectedTypes | (int)Git.FileState.Normal;
352 else
354 m_selectedTypes = m_selectedTypes & (int)~Git.FileState.Normal;
356 OnRefreshTree(null, null);
359 private void OnShowEdited(object sender, EventArgs e)
361 if (((ToolStripButton)sender).Checked)
363 m_selectedTypes = m_selectedTypes | (int)Git.FileState.Modified;
365 else
367 m_selectedTypes = m_selectedTypes & (int)~Git.FileState.Modified;
369 OnRefreshTree(null, null);
372 private void OnShowDeleted(object sender, EventArgs e)
374 if (((ToolStripButton)sender).Checked)
376 m_selectedTypes = m_selectedTypes | (int)Git.FileState.Deleted;
378 else
380 m_selectedTypes = m_selectedTypes & (int)~Git.FileState.Deleted;
382 OnRefreshTree(null, null);
385 private void OnShowOther(object sender, EventArgs e)
387 if (((ToolStripButton)sender).Checked)
389 m_selectedTypes = m_selectedTypes | (int)Git.FileState.Modified;
390 m_selectedTypes = m_selectedTypes | (int)Git.FileState.Unknown;
392 else
394 m_selectedTypes = m_selectedTypes & (int)~Git.FileState.Modified;
395 m_selectedTypes = m_selectedTypes & (int)~Git.FileState.Unknown;
397 OnRefreshTree(null, null);
400 private void OnShowUnmerged(object sender, EventArgs e)
402 if (((ToolStripButton)sender).Checked)
404 m_selectedTypes = m_selectedTypes | (int)Git.FileState.Unmerged;
406 else
408 m_selectedTypes = m_selectedTypes & (int)~Git.FileState.Unmerged;
410 OnRefreshTree(null, null);
413 protected void ExpandPath(string s)
415 string[] parts = s.Split(Repo.DirectorySeparator.ToCharArray());
416 TreeNode currentNode = m_rootNode;
417 m_rootNode.Expand();
418 foreach (string part in parts)
420 int idx = currentNode.Nodes.IndexOfKey(part);
421 if (idx > -1)
423 currentNode = currentNode.Nodes[idx];
424 currentNode.Expand();
429 private void OnRefreshTree(object sender, EventArgs e)
431 if (null != m_workspaceTree.SelectedNode)
433 object o = m_workspaceTree.SelectedNode.Tag;
434 ResetRepoTree(m_currentRepo);
435 this.Enabled = false;
436 foreach (string s in m_expandedPaths.Keys)
438 ExpandPath(s);
440 this.Enabled = true;
444 private void OnAddFiles(object sender, EventArgs e)
446 Enabled = false;
447 if (m_workspaceTree.SelectedNode.Tag is Git.File)
449 Git.File f = (Git.File)m_workspaceTree.SelectedNode.Tag;
450 List<string> paths = new List<string>();
451 if (f.RelativePath.Length > 0)
453 paths.Add(f.RelativePath + Repo.DirectorySeparator + f.Name);
455 else
457 paths.Add(f.Name);
459 List<Git.File> files;
460 if (m_currentRepo.Add(paths, out files))
462 Git.File updatedFile = files[0];
463 if (0 != ((int)updatedFile.State & m_selectedTypes))
465 m_workspaceTree.SelectedNode.Tag = files[0];
466 SetNodeImage(m_workspaceTree.SelectedNode, files[0]);
470 Enabled = true;
473 private void OnDeleteFiles(object sender, EventArgs e)
475 Enabled = false;
476 if (m_workspaceTree.SelectedNode.Tag is Git.File)
478 Git.File f = (Git.File)m_workspaceTree.SelectedNode.Tag;
479 List<string> paths = new List<string>();
480 if (f.RelativePath.Length > 0)
482 paths.Add(f.RelativePath + Repo.DirectorySeparator + f.Name);
484 else
486 paths.Add(f.Name);
488 List<Git.File> files;
489 if (m_currentRepo.Remove(paths, out files))
491 m_workspaceTree.SelectedNode.Tag = files[0];
492 SetNodeImage(m_workspaceTree.SelectedNode, files[0]);
495 Enabled = true;
498 private void OnRevertFiles(object sender, EventArgs e)
500 if (m_workspaceTree.SelectedNode.Tag is Git.File)
502 Git.File f = (Git.File)m_workspaceTree.SelectedNode.Tag;
503 List<string> paths = new List<string>();
504 if (f.RelativePath.Length > 0)
506 paths.Add(f.RelativePath + Repo.DirectorySeparator + f.Name);
508 else
510 paths.Add(f.Name);
512 List<Git.File> files;
513 if (m_currentRepo.Revert(paths, out files))
515 m_workspaceTree.SelectedNode.Tag = files[0];
516 SetNodeImage(m_workspaceTree.SelectedNode, files[0]);
521 private void OnResetHard(object sender, EventArgs e)
523 DialogResult r = MessageBox.Show("Are you sure you want to revert everything you have in your working directory?",
524 "Gitrdone", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
525 if (r == DialogResult.Yes)
527 m_currentRepo.Reset(null);
528 ResetRepoTree(m_currentRepo);
532 private void OnCopyFiles(object sender, EventArgs e)
537 private void OnMoveFiles(object sender, EventArgs e)
542 private void OnShowAdded(object sender, EventArgs e)
547 private void OnShowCopied(object sender, EventArgs e)
552 private void OnShowRenamed(object sender, EventArgs e)
557 private void OnShowUnmanaged(object sender, EventArgs e)
563 private void OnFetchCommits(object sender, EventArgs e)
565 List<Commit> commits;
566 if (!m_currentRepo.GetLog(null, 100, out commits))
568 MessageBox.Show("Could not get commits.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
569 return;
571 m_topCommits.Clear();
572 m_topCommits.Push(commits[0]);
573 FillCommitList(commits);
576 private void FillCommitList(List<Commit> commits)
578 m_commitsView.BeginUpdate();
579 m_commitsView.Items.Clear();
580 foreach (Commit c in commits)
582 ListViewItem i = new ListViewItem(new string[] { c.ID, c.AuthorName, c.AuthorEmail, c.Date, c.Subject });
583 i.Tag = c;
584 m_commitsView.Items.Add(i);
586 if (commits.Count > 0)
588 m_lastCommitInPage = commits[commits.Count - 1];
590 m_previousCommits.Enabled = m_nextCommits.Enabled = commits.Count != 0;
591 if (m_commitsView.Items.Count != 100)
593 m_nextCommits.Enabled = false;
595 if (m_topCommits.Count < 2)
597 m_previousCommits.Enabled = false;
600 m_commitsView.EndUpdate();
603 private void OnPreviousCommits(object sender, EventArgs e)
605 List<Commit> commits;
606 Commit c = m_topCommits.Pop();
607 if (!m_currentRepo.GetLog(m_topCommits.Peek(), 100, out commits))
609 m_nextCommits.Enabled = false;
610 return;
612 if (commits.Count < 1)
614 m_previousCommits.Enabled = false;
616 else
618 FillCommitList(commits);
622 private void OnNextCommits(object sender, EventArgs e)
624 List<Commit> commits;
625 if (!m_currentRepo.GetLog(m_lastCommitInPage, 100, out commits))
627 m_nextCommits.Enabled = false;
628 return;
630 if (commits.Count < 1)
632 m_nextCommits.Enabled = false;
634 else
636 m_topCommits.Push(commits[0]);
637 FillCommitList(commits);