1 /*
2   KeePass Password Safe - The Open-Source Password Manager
3   Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19 
20 using System;
21 using System.Collections.Generic;
22 using System.ComponentModel;
23 using System.Diagnostics;
24 using System.Drawing;
25 using System.Text;
26 using System.Windows.Forms;
27 
28 using KeePass.App;
29 using KeePass.Native;
30 using KeePass.Resources;
31 using KeePass.UI;
32 
33 using KeePassLib;
34 using KeePassLib.Collections;
35 using KeePassLib.Utility;
36 
37 namespace KeePass.Forms
38 {
39 	/* public sealed class LvfCommand
40 	{
41 		private readonly string m_strText;
42 		public string Text
43 		{
44 			get { return m_strText; }
45 		}
46 
47 		private readonly Action<ListView> m_fAction;
48 		public Action<ListView> Action
49 		{
50 			get { return m_fAction; }
51 		}
52 
53 		public LvfCommand(string strText, Action<ListView> fAction)
54 		{
55 			if(strText == null) throw new ArgumentNullException("strText");
56 			if(fAction == null) throw new ArgumentNullException("fAction");
57 
58 			m_strText = strText;
59 			m_fAction = fAction;
60 		}
61 	} */
62 
63 	public partial class ListViewForm : Form
64 	{
65 		private string m_strTitle = string.Empty;
66 		private string m_strSubTitle = string.Empty;
67 		private string m_strInfo = string.Empty;
68 		private Image m_imgIcon = null;
69 		private List<object> m_lData = new List<object>();
70 		private ImageList m_ilIcons = null;
71 		private Action<ListView> m_fInit = null;
72 
73 		private object m_resItem = null;
74 		public object ResultItem
75 		{
76 			get { return m_resItem; }
77 		}
78 
79 		private object m_resGroup = null;
80 		public object ResultGroup
81 		{
82 			get { return m_resGroup; }
83 		}
84 
85 		private bool m_bEnsureForeground = false;
86 		public bool EnsureForeground
87 		{
88 			get { return m_bEnsureForeground; }
89 			set { m_bEnsureForeground = value; }
90 		}
91 
InitEx(string strTitle, string strSubTitle, string strInfo, Image imgIcon, List<object> lData, ImageList ilIcons, Action<ListView> fInit)92 		public void InitEx(string strTitle, string strSubTitle,
93 			string strInfo, Image imgIcon, List<object> lData,
94 			ImageList ilIcons, Action<ListView> fInit)
95 		{
96 			m_strTitle = (strTitle ?? string.Empty);
97 			m_strSubTitle = (strSubTitle ?? string.Empty);
98 			m_strInfo = (strInfo ?? string.Empty);
99 			m_imgIcon = imgIcon;
100 			if(lData != null) m_lData = lData;
101 
102 			if(ilIcons != null)
103 				m_ilIcons = UIUtil.CloneImageList(ilIcons, true);
104 
105 			m_fInit = fInit;
106 		}
107 
ListViewForm()108 		public ListViewForm()
109 		{
110 			InitializeComponent();
111 			GlobalWindowManager.InitializeForm(this);
112 		}
113 
OnFormLoad(object sender, EventArgs e)114 		private void OnFormLoad(object sender, EventArgs e)
115 		{
116 			// Adjust controls before GlobalWindowManager.AddWindow
117 			// for better compatibility with plugins
118 			Debug.Assert(!m_lblInfo.AutoSize); // For RTL support
119 			m_lblInfo.Text = m_strInfo;
120 			if(m_strInfo.Length == 0)
121 			{
122 				int yLabel = m_lblInfo.Location.Y;
123 				Point ptList = m_lvMain.Location;
124 				Size szList = m_lvMain.Size;
125 
126 				m_lblInfo.Visible = false;
127 				m_lvMain.Location = new Point(ptList.X, yLabel);
128 				m_lvMain.Size = new Size(szList.Width, szList.Height +
129 					ptList.Y - yLabel);
130 			}
131 
132 			GlobalWindowManager.AddWindow(this);
133 
134 			this.Text = m_strTitle;
135 			this.Icon = AppIcons.Default;
136 
137 			BannerFactory.CreateBannerEx(this, m_bannerImage,
138 				m_imgIcon, m_strTitle, m_strSubTitle);
139 
140 			UIUtil.SetExplorerTheme(m_lvMain, true);
141 
142 			if(m_ilIcons != null) m_lvMain.SmallImageList = m_ilIcons;
143 
144 			if(m_fInit != null)
145 			{
146 				try { m_fInit(m_lvMain); }
147 				catch(Exception) { Debug.Assert(false); }
148 			}
149 
150 			m_lvMain.BeginUpdate();
151 
152 			ListViewGroup lvgCur = null;
153 			foreach(object o in m_lData)
154 			{
155 				if(o == null) { Debug.Assert(false); continue; }
156 
157 				ListViewItem lvi = (o as ListViewItem);
158 				if(lvi != null)
159 				{
160 					// Caller should not care about associations
161 					Debug.Assert(lvi.ListView == null);
162 					Debug.Assert(lvi.Group == null);
163 
164 					m_lvMain.Items.Add(lvi);
165 					if(lvgCur != null) lvgCur.Items.Add(lvi);
166 
167 					Debug.Assert(lvi.ListView == m_lvMain);
168 					Debug.Assert(lvi.Group == lvgCur);
169 					continue;
170 				}
171 
172 				ListViewGroup lvg = (o as ListViewGroup);
173 				if(lvg != null)
174 				{
175 					// Caller should not care about associations
176 					Debug.Assert(lvg.ListView == null);
177 
178 					m_lvMain.Groups.Add(lvg);
179 					lvgCur = lvg;
180 
181 					Debug.Assert(lvg.ListView == m_lvMain);
182 					continue;
183 				}
184 
185 				Debug.Assert(false); // Unknown data type
186 			}
187 
188 			m_lvMain.EndUpdate();
189 
190 			if(m_bEnsureForeground)
191 			{
192 				this.BringToFront();
193 				this.Activate();
194 			}
195 		}
196 
CleanUpEx()197 		private void CleanUpEx()
198 		{
199 			if(m_ilIcons != null)
200 			{
201 				m_lvMain.SmallImageList = null; // Detach event handlers
202 				m_ilIcons.Dispose();
203 				m_ilIcons = null;
204 			}
205 		}
206 
OnFormClosed(object sender, FormClosedEventArgs e)207 		private void OnFormClosed(object sender, FormClosedEventArgs e)
208 		{
209 			CleanUpEx();
210 			GlobalWindowManager.RemoveWindow(this);
211 		}
212 
CreateResult()213 		private bool CreateResult()
214 		{
215 			ListView.SelectedListViewItemCollection lvic = m_lvMain.SelectedItems;
216 			if(lvic.Count != 1) { Debug.Assert(false); return false; }
217 
218 			ListViewItem lvi = lvic[0];
219 			if(lvi == null) { Debug.Assert(false); return false; }
220 
221 			m_resItem = lvi.Tag;
222 			m_resGroup = ((lvi.Group != null) ? lvi.Group.Tag : null);
223 			return true;
224 		}
225 
ProcessItemSelection()226 		private void ProcessItemSelection()
227 		{
228 			if(this.DialogResult == DialogResult.OK) return; // Already closing
229 
230 			if(CreateResult()) this.DialogResult = DialogResult.OK;
231 		}
232 
OnListItemActivate(object sender, EventArgs e)233 		private void OnListItemActivate(object sender, EventArgs e)
234 		{
235 			ProcessItemSelection();
236 		}
237 
238 		// The item activation handler has a slight delay when clicking an
239 		// item, thus as a performance optimization we additionally handle
240 		// item clicks
OnListClick(object sender, EventArgs e)241 		private void OnListClick(object sender, EventArgs e)
242 		{
243 			ProcessItemSelection();
244 		}
245 	}
246 }
247