Ejemplo n.º 1
0
        protected override void OnLoad(EventArgs args)
        {
            base.OnLoad(args);
            UpdateTitle();

            // Step 1. Bind apriori known actions

            Action <ToolStripItem, Func <ICommand> > bind =
                (mi, fcmd) => Ctx.BindCommand((ToolStripMenuItem)mi, fcmd);

            bind(_vaultNew, () => new VaultNewCommand(Ctx));
            bind(_vaultOpen, () => new VaultOpenCommand(Ctx));
            bind(_vaultSave, () => new VaultSaveCommand(Ctx));
            bind(_vaultImport, () => new VaultImportCommand(Ctx));
            bind(_vaultExport, () => new VaultExportCommand(Ctx));
            bind(_vaultExit, () => new VaultExitCommand(Ctx));

            bind(_editUndo, () => new UndoCommand(Ctx));
            bind(_editRedo, () => new RedoCommand(Ctx));

            bind(_branchNew, () => new BranchNewCommand(Ctx));
            bind(_branchNewPopup, () => new BranchNewCommand(Ctx));
            bind(_branchEditMetadata, () => new BranchEditMetadataStartCommand(Ctx));
            bind(_branchEditMetadataPopup, () => new BranchEditMetadataStartCommand(Ctx));
            bind(_branchDelete, () => new BranchDeleteCommand(Ctx));
            bind(_branchDeletePopup, () => new BranchDeleteCommand(Ctx));
            bind(_branchRename, () => new BranchRenameStartCommand(Ctx));
            bind(_branchRenamePopup, () => new BranchRenameStartCommand(Ctx));
            bind(_branchMoveUp, () => new BranchMoveUpCommand(Ctx));
            bind(_branchMoveUpPopup, () => new BranchMoveUpCommand(Ctx));
            bind(_branchMoveDown, () => new BranchMoveDownCommand(Ctx));
            bind(_branchMoveDownPopup, () => new BranchMoveDownCommand(Ctx));

            bind(_valueEdit, () => new ValueEditStartCommand(Ctx));
            bind(_valueEditPopup, () => new ValueEditStartCommand(Ctx));
            bind(_valueEditMetadata, () => new ValueEditMetadataStartCommand(Ctx));
            bind(_valueEditMetadataPopup, () => new ValueEditMetadataStartCommand(Ctx));
            bind(_valueRename, () => new ValueRenameStartCommand(Ctx));
            bind(_valueRenamePopup, () => new ValueRenameStartCommand(Ctx));
            bind(_valueDelete, () => new ValueDeleteCommand(Ctx));
            bind(_valueDeletePopup, () => new ValueDeleteCommand(Ctx));

            bind(_editCut, () => new CutCommand(Ctx));
            bind(_editCopy, () => new CopyCommand(Ctx));
            bind(_editPaste, () => new PasteCommand(Ctx));
            bind(_branchCutPopup, () => new BranchCutCommand(Ctx));
            bind(_branchCopyPopup, () => new BranchCopyCommand(Ctx));
            bind(_branchPastePopup, () => new BranchPasteCommand(Ctx));
            bind(_valueCutPopup, () => new ValueCutCommand(Ctx));
            bind(_valueCopyPopup, () => new ValueCopyCommand(Ctx));
            bind(_valuePastePopup, () => new ValuePasteCommand(Ctx));
            bind(_valueCutPopup2, () => new ValueCutCommand(Ctx));
            bind(_valueCopyPopup2, () => new ValueCopyCommand(Ctx));
            bind(_valuePastePopup2, () => new ValuePasteCommand(Ctx));

            // Step 2. Generate and bind value creation actions

            Action <ToolStripItemCollection> generateAndBind = coll =>
            {
                var generated = ContentTypes.All.ToDictionary(t => new ToolStripMenuItem(t.LocNewValue)
                {
                    Tag = t
                }, t => t);
                generated.ForEach(kvp => bind(kvp.Key, () => new ValueNewTypedCommand(Ctx, kvp.Value.TypeToken)));

                var binary = new ToolStripMenuItem(Resources.New_ValueBinary);
                bind(binary, () => new ValueNewBinaryCommand(Ctx));

                var dummy = coll.Cast <ToolStripItem>().Single(item => item.Name.Contains("Dummy"));
                var index = coll.IndexOf(dummy);

                dummy.Visible = false;
                coll.Insert(index, binary);
                generated.ForEach(kvp => coll.Insert(index, kvp.Key));
            };

            generateAndBind(_value.DropDownItems);
            generateAndBind(_branchPopup.Items);
            generateAndBind(_valuePopup2.Items);

            // Step 3. Generate and bind view actions

            var map = new Dictionary <String, ToolStripMenuItem>();

            VaultViewFactories.All.OrderBy(v => v.LocName).ForEach(v =>
            {
                var nameTemplate  = Resources.Views_MenuItem_Template;
                var moduleVersion = v.Type.Assembly.GetName().Version.ToString();
                var miName        = String.Format(nameTemplate, v.LocName, moduleVersion);

                var mi = new ToolStripMenuItem(miName);
                map.Add(v.Name, mi);
                _views.DropDownItems.Add(mi);
                bind(mi, () => new ViewToggleCommand(Ctx, v.Name));
            });

            _views.Tag = map; // hack

            // rearrange menu items on view stack changes: push...
            Ctx.Views.ItemPushed += (o, e) =>
            {
                var mi = map[e.Item.Name];
                mi.Checked = true;
                _views.DropDownItems.Remove(mi);
                var iofSep = _views.DropDownItems.IndexOf(_separator13);
                _views.DropDownItems.Insert(iofSep, mi);
            };

            // ...and pop
            Ctx.Views.ItemPopped += (o, e) =>
            {
                var mi = map[e.Item.Name];
                mi.Checked = false;
                _views.DropDownItems.Remove(mi);

                var iofDummy            = _views.DropDownItems.IndexOf(_viewsAvailableDummy);
                var lo                  = iofDummy;
                var hi                  = _views.DropDownItems.Count;
                Func <int, String> text = i =>
                                          i == iofDummy ? "\x0000" :
                                          i == _views.DropDownItems.Count ? "\xffff" :
                                          _views.DropDownItems[i].Text;

                while (hi - lo > 1)
                {
                    var mid = (int)Math.Ceiling((lo + hi) / 2.0);
                    var cmp = String.CompareOrdinal(text(mid), mi.Text);
                    (cmp != 0).AssertTrue();
                    if (cmp == -1)
                    {
                        lo = mid;
                    }
                    if (cmp == 1)
                    {
                        hi = mid;
                    }
                }

                // insert in the exact position to remain sorted
                _views.DropDownItems.Insert(lo + 1, mi);
            };

            // update visibility of menu parts
            _commands.AfterUIResync += (o, e) =>
            {
                var active    = Ctx.Views.ToArray();
                var available = VaultViewFactories.All.Where(v_av =>
                                                             !active.Any(v_ac => v_ac.Name == v_av.Name)).ToArray();

                _views.Visible          = active.IsNotEmpty() || available.IsNotEmpty();
                _viewsActive.Visible    = active.IsNotEmpty();
                _separator13.Visible    = active.IsNotEmpty() && available.IsNotEmpty();
                _viewsAvailable.Visible = available.IsNotEmpty();

                var realMenuItems = _views.DropDownItems.OfType <ToolStripMenuItem>()
                                    .Except(new[] { _viewsActive, _viewsAvailable })
                                    .Where(mi => !mi.Name.ToLower().Contains("dummy"));
                _views.Enabled = realMenuItems.Any(mi => mi.Enabled);
            };

            // Step 4. Ensure event sources are always synced with the commands

            _commands.ResyncUI();
            _tree.AfterSelect          += (o, e) => _commands.ResyncUI();
            _tree.NodeMouseClick       += (o, e) => { _tree.SelectedNode = e.Node; _commands.ResyncUI(); };
            _list.SelectedIndexChanged += (o, e) => _commands.ResyncUI();
            _tree.LostFocus            += (o, e) => _commands.ResyncUI();
            _tree.GotFocus             += (o, e) => _commands.ResyncUI();
            _list.LostFocus            += (o, e) => _commands.ResyncUI();
            _list.GotFocus             += (o, e) => _commands.ResyncUI();

            // Step 5. Ensure that only one command can be executed at a time

            Ctx.CommandExecuting            += (o, e) => { Ctx.CommandsAllowed = false; _commands.ResyncUI(); };
            Ctx.CommandUnexecuting          += (o, e) => { Ctx.CommandsAllowed = false; _commands.ResyncUI(); };
            Ctx.CommandExecutionCancelled   += (o, e) => { Ctx.CommandsAllowed = true; _commands.ResyncUI(); };
            Ctx.CommandUnexecutionCancelled += (o, e) => { Ctx.CommandsAllowed = true; _commands.ResyncUI(); };
            Ctx.CommandExecuted             += (o, e) => { Ctx.CommandsAllowed = true; _commands.ResyncUI(); };
            Ctx.CommandUnexecuted           += (o, e) => { Ctx.CommandsAllowed = true; _commands.ResyncUI(); };

            // Step 6. Setup UI update feedback

            _tree.AfterSelect        += (o, e) => Ctx.RebuildListItems();
            Ctx.CommandExecuted      += (o, e) => UpdateTitle();
            _commands.BeforeUIResync += (o, e) => { if (BeforeUIResync != null)
                                                    {
                                                        BeforeUIResync(o, e);
                                                    }
            };
            _commands.AfterUIResync += (o, e) => { if (AfterUIResync != null)
                                                   {
                                                       AfterUIResync(o, e);
                                                   }
            };

            // Step 7. Load UI extensions
            _extensions = DataVaultUIExtensions.All.ToArray();
            _extensions.ForEach(ext => ext.Initialize(Ctx));

            // 8. Now once we're all started, we can proceed to loading vault from initial URI
            LoadFromInitialUri();
        }