1 /*
2  *  "GEDKeeper", the personal genealogical database editor.
3  *  Copyright (C) 2009-2019 by Sergey V. Zhdanovskih.
4  *
5  *  This file is part of "GEDKeeper".
6  *
7  *  This program is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 using System;
22 using BSLib;
23 using Eto.Drawing;
24 using Eto.Forms;
25 using GKCore;
26 using GKCore.Lists;
27 using GKCore.Types;
28 using BSDListItem = BSLib.Design.MVP.Controls.IListItem;
29 
30 namespace GKUI.Components
31 {
32     /// <summary>
33     ///
34     /// </summary>
35     public class GKSheetList : Panel, ISheetList
36     {
37         private readonly Button fBtnAdd;
38         private readonly Button fBtnDelete;
39         private readonly Button fBtnEdit;
40         private readonly Button fBtnLinkJump;
41         private readonly Button fBtnMoveUp;
42         private readonly Button fBtnMoveDown;
43         private readonly GKListView fList;
44 
45         private EnumSet<SheetButton> fButtons;
46         private ListModel fListModel;
47         private bool fReadOnly;
48 
49 
50         public event ModifyEventHandler OnModify;
51 
52         public event ItemValidatingEventHandler OnItemValidating;
53 
54         public event ModifyEventHandler OnBeforeChange;
55 
56 
57         public EnumSet<SheetButton> Buttons
58         {
59             get { return fButtons; }
60             set {
61                 if (fButtons != value) {
62                     fButtons = value;
63                     UpdateButtons();
64                 }
65             }
66         }
67 
68         public ListModel ListModel
69         {
70             get { return fListModel; }
71             set {
72                 if (fListModel != value) {
73                     if (fListModel != null) {
74                         fListModel.SheetList = null;
75                     }
76 
77                     fListModel = value;
78 
79                     if (fListModel != null) {
80                         fListModel.SheetList = this;
81                     }
82                 }
83 
84                 UpdateSheet();
85             }
86         }
87 
88         public bool ReadOnly
89         {
90             get { return fReadOnly; }
91             set { SetReadOnly(value); }
92         }
93 
94 
GKSheetList(Panel owner)95         public GKSheetList(Panel owner)
96         {
97             if (owner == null)
98                 throw new ArgumentNullException("owner");
99 
100             fBtnMoveDown = new Button();
101             fBtnMoveDown.Image = UIHelper.LoadResourceImage("Resources.btn_down.gif");
102             fBtnMoveDown.Size = UIHelper.ShortButtonSize;
103             fBtnMoveDown.ToolTip = LangMan.LS(LSID.LSID_RecordMoveDown);
104             fBtnMoveDown.Click += ItemMoveDown;
105 
106             fBtnMoveUp = new Button();
107             fBtnMoveUp.Image = UIHelper.LoadResourceImage("Resources.btn_up.gif");
108             fBtnMoveUp.Size = UIHelper.ShortButtonSize;
109             fBtnMoveUp.ToolTip = LangMan.LS(LSID.LSID_RecordMoveUp);
110             fBtnMoveUp.Click += ItemMoveUp;
111 
112             fBtnLinkJump = new Button();
113             fBtnLinkJump.Image = UIHelper.LoadResourceImage("Resources.btn_jump.gif");
114             fBtnLinkJump.Size = UIHelper.ShortButtonSize;
115             fBtnLinkJump.ToolTip = LangMan.LS(LSID.LSID_RecordGoto);
116             fBtnLinkJump.Click += ItemJump;
117 
118             fBtnDelete = new Button();
119             fBtnDelete.Image = UIHelper.LoadResourceImage("Resources.btn_rec_delete.gif");
120             fBtnDelete.Size = UIHelper.ShortButtonSize;
121             fBtnDelete.ToolTip = LangMan.LS(LSID.LSID_MIRecordDelete);
122             fBtnDelete.Click += ItemDelete;
123 
124             fBtnEdit = new Button();
125             fBtnEdit.Image = UIHelper.LoadResourceImage("Resources.btn_rec_edit.gif");
126             fBtnEdit.Size = UIHelper.ShortButtonSize;
127             fBtnEdit.ToolTip = LangMan.LS(LSID.LSID_MIRecordEdit);
128             fBtnEdit.Click += ItemEdit;
129 
130             fBtnAdd = new Button();
131             fBtnAdd.Image = UIHelper.LoadResourceImage("Resources.btn_rec_new.gif");
132             fBtnAdd.Size = UIHelper.ShortButtonSize;
133             fBtnAdd.ToolTip = LangMan.LS(LSID.LSID_MIRecordAdd);
134             fBtnAdd.Click += ItemAdd;
135 
136             fList = new GKListView();
137             fList.MouseDoubleClick += List_DoubleClick;
138             fList.KeyDown += List_KeyDown;
139 
140             SuspendLayout();
141 
142             var toolbar = new DefStackLayout(Orientation.Vertical, 4,
143                                              fBtnAdd, fBtnEdit, fBtnDelete,
144                                              fBtnLinkJump, fBtnMoveUp, fBtnMoveDown);
145 
146             var tab = new TableLayout(2, 1);
147             tab.Spacing = new Size(4, 4);
148             tab.SetColumnScale(0, true);
149             tab.SetColumnScale(1, false);
150             tab.Add(fList, 0, 0);
151             tab.Add(toolbar, 1, 0);
152 
153             Content = tab;
154             ResumeLayout();
155 
156             owner.SuspendLayout();
157             owner.Content = this;
158             owner.ResumeLayout();
159 
160             fButtons = EnumSet<SheetButton>.Create(SheetButton.lbAdd, SheetButton.lbEdit, SheetButton.lbDelete);
161             fListModel = null;
162         }
163 
Dispose(bool disposing)164         protected override void Dispose(bool disposing)
165         {
166             if (disposing)
167             {
168                 fList.Dispose();
169                 fBtnLinkJump.Dispose();
170                 fBtnMoveUp.Dispose();
171                 fBtnMoveDown.Dispose();
172                 fBtnDelete.Dispose();
173                 fBtnEdit.Dispose();
174                 fBtnAdd.Dispose();
175             }
176             base.Dispose(disposing);
177         }
178 
Activate()179         public void Activate()
180         {
181             Focus();
182         }
183 
184         #region Private methods
185 
UpdateButtons()186         private void UpdateButtons()
187         {
188             if (fListModel == null) {
189                 fBtnAdd.Visible = fButtons.Contains(SheetButton.lbAdd);
190                 fBtnDelete.Visible = fButtons.Contains(SheetButton.lbDelete);
191                 fBtnEdit.Visible = fButtons.Contains(SheetButton.lbEdit);
192                 fBtnLinkJump.Visible = fButtons.Contains(SheetButton.lbJump);
193                 fBtnMoveUp.Visible = fButtons.Contains(SheetButton.lbMoveUp);
194                 fBtnMoveDown.Visible = fButtons.Contains(SheetButton.lbMoveDown);
195                 //fToolBar.Enabled = !fButtons.IsEmpty();
196             } else {
197                 EnumSet<RecordAction> allowedActions = fListModel.AllowedActions;
198                 fBtnAdd.Visible = allowedActions.Contains(RecordAction.raAdd);
199                 fBtnDelete.Visible = allowedActions.Contains(RecordAction.raDelete);
200                 fBtnEdit.Visible = allowedActions.Contains(RecordAction.raEdit);
201                 fBtnLinkJump.Visible = allowedActions.Contains(RecordAction.raJump);
202                 fBtnMoveUp.Visible = allowedActions.Contains(RecordAction.raMoveUp);
203                 fBtnMoveDown.Visible = allowedActions.Contains(RecordAction.raMoveDown);
204                 //fToolBar.Visible = !allowedActions.IsEmpty();
205             }
206         }
207 
SetReadOnly(bool value)208         private void SetReadOnly(bool value)
209         {
210             fReadOnly = value;
211             fBtnAdd.Enabled = !fReadOnly;
212             fBtnDelete.Enabled = !fReadOnly;
213             fBtnEdit.Enabled = !fReadOnly;
214             fBtnMoveUp.Enabled = !fReadOnly;
215             fBtnMoveDown.Enabled = !fReadOnly;
216 
217             fList.BackgroundColor = (fReadOnly) ? SystemColors.Control : SystemColors.WindowBackground;
218         }
219 
List_DoubleClick(object sender, EventArgs e)220         private void List_DoubleClick(object sender, EventArgs e)
221         {
222             ItemEdit(sender, e);
223         }
224 
List_KeyDown(object sender, KeyEventArgs e)225         private void List_KeyDown(object sender, KeyEventArgs e)
226         {
227             if (e.Control)
228             {
229                 switch (e.Key) {
230                     case Keys.I:
231                         ItemAdd(sender, e);
232                         break;
233                     case Keys.D:
234                         ItemDelete(sender, e);
235                         break;
236                     case Keys.Enter:
237                         ItemEdit(sender, e);
238                         break;
239                 }
240             }
241         }
242 
RestoreSelected(object itemData)243         private void RestoreSelected(object itemData)
244         {
245             Activate();
246             fList.Activate();
247 
248             if (itemData != null) fList.SelectItem(itemData);
249         }
250 
DoBeforeChange(ModifyEventArgs eArgs)251         private void DoBeforeChange(ModifyEventArgs eArgs)
252         {
253             var eventHandler = (ModifyEventHandler)OnBeforeChange;
254             if (eventHandler != null) {
255                 eventHandler(this, eArgs);
256             }
257         }
258 
DoModify(ModifyEventArgs eArgs)259         private void DoModify(ModifyEventArgs eArgs)
260         {
261             DoBeforeChange(eArgs);
262 
263             if (fListModel != null) {
264                 fListModel.Modify(this, eArgs);
265 
266                 if (eArgs.IsChanged) {
267                     UpdateSheet();
268                 }
269             }
270 
271             var eventHandler = (ModifyEventHandler)OnModify;
272             if (eventHandler != null) {
273                 eventHandler(this, eArgs);
274             }
275         }
276 
ValidateItem(object item)277         private bool ValidateItem(object item)
278         {
279             var args = new ItemValidatingEventArgs(item);
280 
281             var eventHandler = (ItemValidatingEventHandler)OnItemValidating;
282             if (eventHandler == null)
283             {
284                 return true;
285             }
286 
287             eventHandler(this, args);
288             return args.IsAvailable;
289         }
290 
ItemAdd(object sender, EventArgs e)291         private void ItemAdd(object sender, EventArgs e)
292         {
293             if (fReadOnly) return;
294 
295             var eArgs = new ModifyEventArgs(RecordAction.raAdd, null);
296             DoModify(eArgs);
297             RestoreSelected(eArgs.ItemData);
298         }
299 
ItemEdit(object sender, EventArgs e)300         private void ItemEdit(object sender, EventArgs e)
301         {
302             object itemData = GetSelectedData();
303             if (fReadOnly || itemData == null) return;
304 
305             if (!ValidateItem(itemData)) return;
306 
307             var eArgs = new ModifyEventArgs(RecordAction.raEdit, itemData);
308             DoModify(eArgs);
309             RestoreSelected(eArgs.ItemData);
310         }
311 
ItemDelete(object sender, EventArgs e)312         private void ItemDelete(object sender, EventArgs e)
313         {
314             object itemData = GetSelectedData();
315             if (fReadOnly || itemData == null) return;
316 
317             if (!ValidateItem(itemData)) return;
318 
319             var eArgs = new ModifyEventArgs(RecordAction.raDelete, itemData);
320             DoModify(eArgs);
321         }
322 
ItemJump(object sender, EventArgs e)323         private void ItemJump(object sender, EventArgs e)
324         {
325             object itemData = GetSelectedData();
326             if (itemData == null) return;
327 
328             if (!ValidateItem(itemData)) return;
329 
330             var eArgs = new ModifyEventArgs(RecordAction.raJump, itemData);
331             DoModify(eArgs);
332         }
333 
ItemMoveUp(object sender, EventArgs e)334         private void ItemMoveUp(object sender, EventArgs e)
335         {
336             object itemData = GetSelectedData();
337             if (fReadOnly || itemData == null) return;
338 
339             var eArgs = new ModifyEventArgs(RecordAction.raMoveUp, itemData);
340             DoModify(eArgs);
341             RestoreSelected(eArgs.ItemData);
342         }
343 
ItemMoveDown(object sender, EventArgs e)344         private void ItemMoveDown(object sender, EventArgs e)
345         {
346             object itemData = GetSelectedData();
347             if (fReadOnly || itemData == null) return;
348 
349             var eArgs = new ModifyEventArgs(RecordAction.raMoveDown, itemData);
350             DoModify(eArgs);
351             RestoreSelected(eArgs.ItemData);
352         }
353 
354         #endregion
355 
ClearColumns()356         public void ClearColumns()
357         {
358             fList.ClearColumns();
359         }
360 
ResizeColumn(int columnIndex)361         public void ResizeColumn(int columnIndex)
362         {
363             fList.ResizeColumn(columnIndex);
364         }
365 
AddColumn(string caption, int width, bool autoSize)366         public void AddColumn(string caption, int width, bool autoSize)
367         {
368             fList.AddColumn(caption, width, autoSize);
369         }
370 
BeginUpdate()371         public void BeginUpdate()
372         {
373             fList.BeginUpdate();
374         }
375 
EndUpdate()376         public void EndUpdate()
377         {
378             fList.EndUpdate();
379         }
380 
AddItem(object rowData, params object[] columnValues)381         public BSDListItem AddItem(object rowData, params object[] columnValues)
382         {
383             return fList.AddItem(rowData, columnValues);
384         }
385 
ClearItems()386         public void ClearItems()
387         {
388             fList.ClearItems();
389         }
390 
SelectItem(int index)391         public void SelectItem(int index)
392         {
393             fList.SelectItem(index);
394         }
395 
UpdateSheet()396         public void UpdateSheet()
397         {
398             UpdateButtons();
399 
400             if (fListModel != null) {
401                 if (fList.Columns.Count == 0 || fListModel.ColumnsHaveBeenChanged) {
402                     fList.ClearColumns();
403                     fListModel.UpdateColumns(fList);
404                 }
405 
406                 fListModel.UpdateContents();
407             }
408         }
409 
GetSelectedData()410         public object GetSelectedData()
411         {
412             return fList.GetSelectedData();
413         }
414     }
415 }
416