public static IDialogView CreateDialog( NSWindow parentWindow, IChangeNotification changeNotification, IDialogViewModel viewModel, IEnumerable <string> tags, string initiallyFocusedTag ) { var dlg = new TagsSelectionSheetController(parentWindow, viewModel); dlg.Window.GetHashCode(); int focusedRow = -1; foreach (var t in tags) { var b = new NSButton() { Title = t, State = NSCellStateValue.Off }; b.SetButtonType(NSButtonType.Switch); if (initiallyFocusedTag == t) { focusedRow = dlg.views.Count; } b.Action = new ObjCRuntime.Selector("OnTagChecked:"); b.Target = dlg; dlg.views.Add(b); } dlg.table.Delegate = new Delegate() { owner = dlg }; dlg.table.DataSource = new DataSource() { owner = dlg }; if (focusedRow >= 0) { dlg.table.SelectRow(focusedRow, byExtendingSelection: false); dlg.table.ScrollRowToVisible(focusedRow); } dlg.linkLabel.StringValue = "select: all none"; dlg.linkLabel.Links = new [] { new NSLinkLabel.Link(8, 3, ""), new NSLinkLabel.Link(14, 4, null), }; dlg.formulaTextView.Delegate = new TextViewDelegate() { view = dlg.formulaTextView, viewModel = viewModel, changeNotification = changeNotification }; dlg.linkLabel.LinkClicked = (s, e) => { if (e.Link.Tag != null) { viewModel.OnUseAllClicked(); } else { viewModel.OnUnuseAllClicked(); } }; var updateCheckboxes = Updaters.Create( () => viewModel.SelectedTags, () => viewModel.IsEditingFormula, (selected, editing) => { dlg.views.ForEach(b => { b.State = selected.Contains(b.Title) ? NSCellStateValue.On : NSCellStateValue.Off; b.Enabled = !editing; }); } ); NSColor getLinkColor(MessageSeverity sev) => sev == MessageSeverity.Error ? NSColor.Red : sev == MessageSeverity.Warning ? NSColor.Orange : NSColor.Text; var updateFormula = Updaters.Create( () => viewModel.Formula, () => viewModel.IsEditingFormula, () => viewModel.FormulaStatus, (formula, editing, status) => { if (dlg.formulaTextView.Value != formula) { dlg.formulaTextView.Value = formula; } dlg.formulaTextView.Editable = editing; dlg.formulaTextView.BackgroundColor = editing ? NSColor.TextBackground : NSColor.ControlBackground; dlg.formulaTextView.TextColor = editing ? NSColor.Text : NSColor.PlaceholderTextColor; dlg.linkLabel.IsEnabled = !editing; dlg.okButton.Enabled = !editing; dlg.formulaEditLinkLabel.StringValue = editing ? "done" : "edit"; var(statusText, statusSeverity) = status; dlg.formulaLinkLabel.SetAttributedContents(statusText); dlg.formulaEditLinkLabel.IsEnabled = statusSeverity != MessageSeverity.Error; dlg.formulaLinkLabel.TextColor = getLinkColor(statusSeverity); } ); var formulaFocusSideEffect = Updaters.Create( () => viewModel.IsEditingFormula, editing => { if (editing) { dlg.Window.MakeFirstResponder(dlg.formulaTextView); } } ); var updateSuggestions = Updaters.Create( () => viewModel.FormulaSuggesions, value => { var(list, selectedItem) = value; dlg.suggestionsContainer.Hidden = list.IsEmpty; dlg.suggestionsLabel.Hidden = list.IsEmpty; dlg.suggestionsView.Subviews.ToList().ForEach(v => v.RemoveFromSuperview()); var itemHeight = 17; nfloat maxRight = 0; var views = list.Select((str, idx) => { var lbl = NSLinkLabel.CreateLabel(str); lbl.BackgroundColor = idx == selectedItem ? NSColor.SelectedTextBackground : NSColor.Clear; lbl.TextColor = idx == selectedItem ? NSColor.SelectedText : NSColor.Text; lbl.LinkClicked = (s, e) => viewModel.OnSuggestionClicked(idx); lbl.SetFrameOrigin(new CoreGraphics.CGPoint(5, idx * itemHeight)); lbl.SetFrameSize(lbl.IntrinsicContentSize); return(lbl); }).ToList(); foreach (var subView in views) { dlg.suggestionsView.AddSubview(subView); maxRight = (nfloat)Math.Max(maxRight, subView.Frame.Right); } dlg.suggestionsView.SetFrameSize(new CoreGraphics.CGSize(maxRight, list.Length * itemHeight)); if (selectedItem != null) { dlg.suggestionsView.ScrollRectToVisible(views[selectedItem.Value].Frame); } } ); var listStatusUpdater = Updaters.Create( () => viewModel.TagsListStatus, (status) => { var(statusText, statusSeverity) = status; dlg.tagsStatusLinkLabel.SetAttributedContents(statusText); dlg.tagsStatusLinkLabel.TextColor = getLinkColor(statusSeverity); } ); dlg.subscription = changeNotification.CreateSubscription(() => { updateCheckboxes(); updateFormula(); formulaFocusSideEffect(); updateSuggestions(); listStatusUpdater(); }, initiallyActive: false); dlg.formulaEditLinkLabel.LinkClicked = (sender, e) => { if (viewModel.IsEditingFormula) { viewModel.OnStopEditingFormulaClicked(); } else { viewModel.OnEditFormulaClicked(); } }; dlg.formulaLinkLabel.LinkClicked = (sender, e) => viewModel.OnFormulaLinkClicked(e.Link.Tag as string); dlg.tagsStatusLinkLabel.LinkClicked = (sender, e) => viewModel.OnTagsStatusLinkClicked(e.Link.Tag as string); return(dlg); }
public AllTagsDialog( IChangeNotification changeNotification, IDialogViewModel viewModel, IEnumerable <string> availableTags, string initiallyFocusedTag ) { this.viewModel = viewModel; InitializeComponent(); checkedListBox1.BeginUpdate(); int focusedTagIndex = -1; foreach (var t in availableTags) { var idx = checkedListBox1.Items.Add(t); if (initiallyFocusedTag != null && t == initiallyFocusedTag) { focusedTagIndex = idx; } } checkedListBox1.EndUpdate(); if (focusedTagIndex >= 0) { checkedListBox1.SelectedIndex = focusedTagIndex; checkedListBox1.TopIndex = focusedTagIndex; } var listUpdater = Updaters.Create( () => viewModel.SelectedTags, () => viewModel.IsEditingFormula, (selected, editingFormula) => { checkedListBox1.Tag = "ignore events"; checkedListBox1.BeginUpdate(); foreach (var t in availableTags.ZipWithIndex()) { checkedListBox1.SetItemChecked(t.Key, selected.Contains(t.Value)); } checkedListBox1.Enabled = !editingFormula; checkedListBox1.EndUpdate(); checkedListBox1.Tag = null; } ); Color getLinkColor(MessageSeverity sev) => sev == MessageSeverity.Error ? Color.Red : sev == MessageSeverity.Warning ? Color.DarkOrange : SystemColors.WindowText; var formulaUpdater = Updaters.Create( () => viewModel.Formula, () => viewModel.IsEditingFormula, () => viewModel.FormulaStatus, (formula, editing, status) => { formulaTextBox.Text = formula; formulaTextBox.ReadOnly = !editing; checkAllLinkLabel.Enabled = !editing; checkNoneLinkLabel.Enabled = !editing; okButton.Enabled = !editing; formulaLinkLabel.Text = editing ? "done" : "edit"; var(statusText, statusSeverity) = status; UIUtils.SetLinkContents(formulaStatusLinkLabel, statusText); formulaLinkLabel.Enabled = statusSeverity != MessageSeverity.Error; formulaStatusLinkLabel.ForeColor = getLinkColor(statusSeverity); } ); var formulaFocusSideEffect = Updaters.Create( () => viewModel.IsEditingFormula, editing => { if (editing && formulaTextBox.CanFocus) { formulaTextBox.Focus(); } } ); var updateSuggestions = Updaters.Create( () => viewModel.FormulaSuggesions, value => { var(list, selectedItem) = value; suggestionsPanel.Visible = !list.IsEmpty; suggestionsPanel.Controls.Clear(); suggestionsPanel.Controls.AddRange(list.Select((str, idx) => { var lbl = new Label() { Text = str, AutoSize = true, Left = 4, Top = 2 + idx * (formulaLinkLabel.Height + 3), ForeColor = idx == selectedItem ? SystemColors.HighlightText : SystemColors.ControlText, BackColor = idx == selectedItem ? SystemColors.Highlight : suggestionsPanel.BackColor }; lbl.MouseDown += (s, e) => viewModel.OnSuggestionClicked(idx); return(lbl); }).ToArray()); if (selectedItem != null) { suggestionsPanel.ScrollControlIntoView(suggestionsPanel.Controls[selectedItem.Value]); } } ); var listStatusUpdater = Updaters.Create( () => viewModel.TagsListStatus, (status) => { var(statusText, statusSeverity) = status; UIUtils.SetLinkContents(tagsStatusLinkLabel, statusText); tagsStatusLinkLabel.ForeColor = getLinkColor(statusSeverity); } ); subscription = changeNotification.CreateSubscription(() => { listUpdater(); formulaUpdater(); formulaFocusSideEffect(); updateSuggestions(); listStatusUpdater(); }); detectFormulaCursorPositionChange = Updaters.Create( () => formulaTextBox.SelectionStart, _ => changeNotification.Post() ); checkedListBox1.ItemCheck += (sender, e) => { if (checkedListBox1.Tag != null) { return; } var tag = (string)checkedListBox1.Items[e.Index]; if (e.NewValue == CheckState.Checked) { viewModel.OnUseTagClicked(tag); } else { viewModel.OnUnuseTagClicked(tag); } }; cancelButton.Click += (sender, e) => viewModel.OnCancelDialog(); okButton.Click += (sender, e) => viewModel.OnConfirmDialog(); }