From f3f87a4bf5d55d944884a550a5b8719ef82aa814 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 18 Aug 2009 20:51:26 +0000 Subject: [PATCH] QuickClassBrowser: don't change ComboBox contents while user has opened the drop-down. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4731 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/AvalonEditViewContent.cs | 16 +++++- .../AvalonEdit.AddIn/Src/CodeEditor.cs | 25 ++++++--- .../AvalonEdit.AddIn/Src/QuickClassBrowser.cs | 51 ++++++++++++++++--- .../Src/QuickClassBrowser.xaml | 10 ++-- .../IDEOptions/SelectCulturePanel.cs | 27 +++++----- .../Services/ParserService/ParserService.cs | 14 ++--- 6 files changed, 104 insertions(+), 39 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs index b8278cf429..f9a64ac95c 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs @@ -17,6 +17,7 @@ using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui; +using System.Windows.Threading; namespace ICSharpCode.AvalonEdit.AddIn { @@ -230,9 +231,22 @@ namespace ICSharpCode.AvalonEdit.AddIn #endregion #region IParseInformationListener + ParseInformation updateParseInfoTo; + public void ParseInformationUpdated(ParseInformation parseInfo) { - WorkbenchSingleton.SafeThreadAsyncCall(codeEditor.ParseInformationUpdated, parseInfo); + // When parse information is updated quickly in succession, only do a single update + // to the latest version. + updateParseInfoTo = parseInfo; + codeEditor.Dispatcher.BeginInvoke( + DispatcherPriority.Background, + new Action( + delegate { + if (updateParseInfoTo != null) { + codeEditor.ParseInformationUpdated(updateParseInfoTo); + updateParseInfoTo = null; + } + })); } #endregion } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs index 7ffcd242bc..c35620822e 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs @@ -497,6 +497,13 @@ namespace ICSharpCode.AvalonEdit.AddIn if (c == '\r') c = '\n'; languageBinding.FormattingStrategy.FormatLine(GetAdapterFromSender(sender), c); + + if (c == '\n') { + // Immediately parse on enter. + // This ensures we have up-to-date CC info about the method boundary when a user + // types near the end of a method. + ParserService.BeginParse(this.FileName, this.DocumentAdapter.CreateSnapshot()); + } } } } @@ -606,14 +613,18 @@ namespace ICSharpCode.AvalonEdit.AddIn public void ParseInformationUpdated(ParseInformation parseInfo) { if (parseInfo != null) { - if (quickClassBrowser == null) { - quickClassBrowser = new QuickClassBrowser(); - quickClassBrowser.JumpAction = JumpTo; - SetRow(quickClassBrowser, 0); - this.Children.Add(quickClassBrowser); + // don't create quickClassBrowser for files that don't have any classes + // (but do keep the quickClassBrowser when the last class is removed from a file) + if (quickClassBrowser != null || parseInfo.CompilationUnit.Classes.Count > 0) { + if (quickClassBrowser == null) { + quickClassBrowser = new QuickClassBrowser(); + quickClassBrowser.JumpAction = JumpTo; + SetRow(quickClassBrowser, 0); + this.Children.Add(quickClassBrowser); + } + quickClassBrowser.Update(parseInfo.CompilationUnit); + quickClassBrowser.SelectItemAtCaretPosition(this.ActiveTextEditorAdapter.Caret.Position); } - quickClassBrowser.Update(parseInfo.MostRecentCompilationUnit); - quickClassBrowser.SelectItemAtCaretPosition(this.ActiveTextEditorAdapter.Caret.Position); } else { if (quickClassBrowser != null) { this.Children.Remove(quickClassBrowser); diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs index 2d6bcb742b..08b58465c9 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs @@ -99,17 +99,25 @@ namespace ICSharpCode.AvalonEdit.AddIn InitializeComponent(); } - // The lists of items currently visible in the combo boxes. - // These should never be null. - List classItems = new List(); - List memberItems = new List(); - /// /// Updates the list of available classes. - /// This causes the classes combo box to loose its current selected, + /// This causes the classes combo box to lose its current selection, /// so the members combo box will be cleared. /// public void Update(ICompilationUnit compilationUnit) + { + runUpdateWhenDropDownClosed = true; + runUpdateWhenDropDownClosedCU = compilationUnit; + if (!IsDropDownOpen) + ComboBox_DropDownClosed(null, null); + } + + // The lists of items currently visible in the combo boxes. + // These should never be null. + List classItems = new List(); + List memberItems = new List(); + + void DoUpdate(ICompilationUnit compilationUnit) { classItems = new List(); if (compilationUnit != null) { @@ -119,6 +127,29 @@ namespace ICSharpCode.AvalonEdit.AddIn classComboBox.ItemsSource = classItems; } + bool IsDropDownOpen { + get { return classComboBox.IsDropDownOpen || membersComboBox.IsDropDownOpen; } + } + + // Delayed execution - avoid changing combo boxes while the user is browsing the dropdown list. + bool runUpdateWhenDropDownClosed; + ICompilationUnit runUpdateWhenDropDownClosedCU; + bool runSelectItemWhenDropDownClosed; + Location runSelectItemWhenDropDownClosedLocation; + + void ComboBox_DropDownClosed(object sender, EventArgs e) + { + if (runUpdateWhenDropDownClosed) { + runUpdateWhenDropDownClosed = false; + DoUpdate(runUpdateWhenDropDownClosedCU); + runUpdateWhenDropDownClosedCU = null; + } + if (runSelectItemWhenDropDownClosed) { + runSelectItemWhenDropDownClosed = false; + DoSelectItem(runSelectItemWhenDropDownClosedLocation); + } + } + void AddClasses(IEnumerable classes) { foreach (IClass c in classes) { @@ -131,6 +162,14 @@ namespace ICSharpCode.AvalonEdit.AddIn /// Selects the class and member closest to the specified location. /// public void SelectItemAtCaretPosition(Location location) + { + runSelectItemWhenDropDownClosed = true; + runSelectItemWhenDropDownClosedLocation = location; + if (!IsDropDownOpen) + ComboBox_DropDownClosed(null, null); + } + + void DoSelectItem(Location location) { EntityItem matchInside = null; EntityItem nearestMatch = null; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml index 5a705f9026..c17d8f8748 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml @@ -1,6 +1,8 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + FocusManager.IsFocusScope="True"> + @@ -25,11 +27,13 @@ Grid.Column="0" Margin="0,0,4,1" ItemTemplate="{StaticResource comboBoxItemTemplate}" - SelectionChanged="classComboBoxSelectionChanged"/> + SelectionChanged="classComboBoxSelectionChanged" + DropDownClosed="ComboBox_DropDownClosed"/> + SelectionChanged="membersComboBoxSelectionChanged" + DropDownClosed="ComboBox_DropDownClosed"/> \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SelectCulturePanel.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SelectCulturePanel.cs index 14ef9ff001..3adb27557e 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SelectCulturePanel.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SelectCulturePanel.cs @@ -39,16 +39,13 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels } } -/* public override bool ReceiveDialogMessage(DialogMessage message) + public override bool StorePanelContents() { - if (message == DialogMessage.OK) { - if (SelectedCulture != null) { - PropertyService.Set(uiLanguageProperty, SelectedCulture); - } + if (SelectedCulture != null) { + PropertyService.Set(uiLanguageProperty, SelectedCulture); } return true; } - */ void ChangeCulture(object sender, EventArgs e) { @@ -73,22 +70,22 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels listView.ItemActivate += new EventHandler(ChangeCulture); listView.Sorting = SortOrder.Ascending; listView.Activation = ItemActivation.OneClick; - listView.Anchor = (System.Windows.Forms.AnchorStyles.Top | - (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); + listView.Anchor = (System.Windows.Forms.AnchorStyles.Top | + (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); listView.MultiSelect = false; foreach (Language language in LanguageService.Languages) { listView.Items.Add(new ListViewItem(new string[] {language.Name, language.Code}, language.ImageIndex)); - } + } this.Controls.Add(listView); Label culture = new Label(); culture.Location = new Point(8, 220); culture.Size = new Size(350, 16); - culture.Anchor = (System.Windows.Forms.AnchorStyles.Top | + culture.Anchor = (System.Windows.Forms.AnchorStyles.Top | (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); - + Dock = DockStyle.Fill; culture.Text = ResourceService.GetString("Dialog.Options.IDEOptions.SelectCulture.CurrentUILanguageLabel") + " " + GetCulture(PropertyService.Get(uiLanguageProperty, "en")); @@ -98,15 +95,15 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels descr.Location = new Point(8, 280); descr.Size = new Size(390, 50); descr.Text = ResourceService.GetString("Dialog.Options.IDEOptions.SelectCulture.DescriptionText"); - descr.Anchor = (System.Windows.Forms.AnchorStyles.Top | - (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); + descr.Anchor = (System.Windows.Forms.AnchorStyles.Top | + (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); this.Controls.Add(descr); newCulture.Location = new Point(8, 240); newCulture.Size = new Size(360, 50); - newCulture.Anchor = (System.Windows.Forms.AnchorStyles.Top | - (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); + newCulture.Anchor = (System.Windows.Forms.AnchorStyles.Top | + (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)); this.Controls.Add(newCulture); } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 68d6eedc35..73865ba212 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -137,7 +137,7 @@ namespace ICSharpCode.SharpDevelop { WorkbenchSingleton.DebugAssertMainThread(); timer = new DispatcherTimer(DispatcherPriority.Background); - timer.Interval = TimeSpan.FromSeconds(2); + timer.Interval = TimeSpan.FromSeconds(1.5); timer.Tick += new EventHandler(timer_Tick); timer.Start(); } @@ -733,6 +733,12 @@ namespace ICSharpCode.SharpDevelop WorkbenchSingleton.SafeThreadAsyncCall( delegate { ParseInformationUpdated(null, e); + + IViewContent currentView = WorkbenchSingleton.Workbench.ActiveViewContent; + IParseInformationListener listener = currentView as IParseInformationListener; + if (listener != null && FileUtility.IsEqualFileName(e.FileName, currentView.PrimaryFileName)) { + listener.ParseInformationUpdated(new ParseInformation(e.NewCompilationUnit)); + } }); } @@ -747,12 +753,6 @@ namespace ICSharpCode.SharpDevelop WorkbenchSingleton.SafeThreadAsyncCall( delegate { ParserUpdateStepFinished(null, e); - - IViewContent currentView = WorkbenchSingleton.Workbench.ActiveViewContent; - IParseInformationListener listener = currentView as IParseInformationListener; - if (listener != null && FileUtility.IsEqualFileName(e.FileName, currentView.PrimaryFileName)) { - listener.ParseInformationUpdated(e.ParseInformation); - } }); }