/* * Copyright 2019 faddenSoft * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using CommonWPF; namespace SourceGenWPF.ProjWin { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window, INotifyPropertyChanged { /// /// Disassembled code display list provided to XAML. /// public DisplayList CodeDisplayList { get; private set; } /// /// private MainController mMainCtrl; private MethodInfo listViewSetSelectedItems; public MainWindow() { InitializeComponent(); listViewSetSelectedItems = codeListView.GetType().GetMethod("SetSelectedItems", BindingFlags.NonPublic | BindingFlags.Instance); Debug.Assert(listViewSetSelectedItems != null); this.DataContext = this; CodeDisplayList = new DisplayList(); codeListView.ItemsSource = CodeDisplayList; mMainCtrl = new MainController(this); AddMultiKeyGestures(); //GridView gv = (GridView)codeListView.View; //gv.Columns[0].Width = 50; } private void AddMultiKeyGestures() { RoutedUICommand ruic; ruic = (RoutedUICommand)FindResource("HintAsCodeEntryPoint"); ruic.InputGestures.Add( new MultiKeyInputGesture(new KeyGesture[] { new KeyGesture(Key.H, ModifierKeys.Control, "Ctrl+H"), new KeyGesture(Key.C, ModifierKeys.Control, "Ctrl+C") })); ruic = (RoutedUICommand)FindResource("HintAsDataStart"); ruic.InputGestures.Add( new MultiKeyInputGesture(new KeyGesture[] { new KeyGesture(Key.H, ModifierKeys.Control, "Ctrl+H"), new KeyGesture(Key.D, ModifierKeys.Control, "Ctrl+D") })); ruic = (RoutedUICommand)FindResource("HintAsInlineData"); ruic.InputGestures.Add( new MultiKeyInputGesture(new KeyGesture[] { new KeyGesture(Key.H, ModifierKeys.Control, "Ctrl+H"), new KeyGesture(Key.I, ModifierKeys.Control, "Ctrl+I") })); ruic = (RoutedUICommand)FindResource("RemoveHints"); ruic.InputGestures.Add( new MultiKeyInputGesture(new KeyGesture[] { new KeyGesture(Key.H, ModifierKeys.Control, "Ctrl+H"), new KeyGesture(Key.R, ModifierKeys.Control, "Ctrl+R") })); } private void Window_Loaded(object sender, RoutedEventArgs e) { mMainCtrl.WindowLoaded(); CreateCodeListContextMenu(); #if DEBUG // Get more info on CollectionChanged events that do not agree with current // state of Items collection. PresentationTraceSources.SetTraceLevel(codeListView.ItemContainerGenerator, PresentationTraceLevel.High); #endif } private void CreateCodeListContextMenu() { // Find Actions menu. ItemCollection mainItems = this.appMenu.Items; MenuItem actionsMenu = null; foreach (object obj in mainItems) { if (!(obj is MenuItem)) { continue; } MenuItem mi = (MenuItem)obj; if (mi.Name.Equals("ActionsMenu")) { actionsMenu = mi; break; } } Debug.Assert(actionsMenu != null); // Clone the Actions menu into the codeListView context menu. ContextMenu ctxt = this.codeListView.ContextMenu; foreach (object item in actionsMenu.Items) { if (item is MenuItem) { MenuItem oldItem = (MenuItem)item; MenuItem newItem = new MenuItem(); // I don't see a "clone" method, so just copy the fields we think we care about newItem.Name = oldItem.Name; newItem.Header = oldItem.Header; newItem.Icon = oldItem.Icon; newItem.InputGestureText = oldItem.InputGestureText; newItem.Command = oldItem.Command; ctxt.Items.Add(newItem); } else if (item is Separator) { ctxt.Items.Add(new Separator()); } else { Debug.Assert(false, "Found weird thing in menu: " + item); } } } /// /// INotifyPropertyChanged event /// public event PropertyChangedEventHandler PropertyChanged; /// /// Call this when a notification-worthy property changes value. /// /// The CallerMemberName attribute puts the calling property's name in the first arg. /// /// Name of property that changed. private void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool mShowCodeListView; /// /// Which panel are we showing, launchPanel or codeListView? /// public bool ShowCodeListView { get { return mShowCodeListView; } set { mShowCodeListView = value; OnPropertyChanged("LaunchPanelVisibility"); OnPropertyChanged("CodeListVisibility"); } } /// /// Returns true if we should be showing the launch panel. /// (Intended for use from XAML.) /// public Visibility LaunchPanelVisibility { get { return mShowCodeListView ? Visibility.Hidden : Visibility.Visible; } } /// /// Returns true if we should be showing the code ListView. /// (Intended for use from XAML.) /// public Visibility CodeListVisibility { get { return mShowCodeListView ? Visibility.Visible : Visibility.Hidden; } } /// Version string, for display. /// public string ProgramVersionString { get { return App.ProgramVersion.ToString(); } } /// /// Returns true if the project is open. Intended for use in XAML CommandBindings. /// private void IsProjectOpen(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = mMainCtrl.IsProjectOpen(); } private void AssembleCmd_Executed(object sender, ExecutedRoutedEventArgs e) { // test Debug.WriteLine("assembling"); } private void CloseCmd_Executed(object sender, ExecutedRoutedEventArgs e) { if (!mMainCtrl.CloseProject()) { Debug.WriteLine("Close canceled"); } } private void HintAsCodeEntryPoint_Executed(object sender, ExecutedRoutedEventArgs e) { Debug.WriteLine("hint as code entry point"); } private void HintAsDataStart_Executed(object sender, ExecutedRoutedEventArgs e) { Debug.WriteLine("hint as data start"); } private void HintAsInlineData_Executed(object sender, ExecutedRoutedEventArgs e) { Debug.WriteLine("hint as inline data"); } private void RemoveHints_Executed(object sender, ExecutedRoutedEventArgs e) { Debug.WriteLine("remove hints"); } private void SelectAllCmd_Executed(object sender, ExecutedRoutedEventArgs e) { DateTime start = DateTime.Now; codeListView.SelectAll(); //codeListView.SelectedItems.Clear(); //foreach (var item in codeListView.Items) { // codeListView.SelectedItems.Add(item); //} // This seems to be faster than setting items individually (10x), but is still O(n^2) // or worse, and hence unsuitable for very large lists. //codeListView.SelectedItems.Clear(); //listViewSetSelectedItems.Invoke(codeListView, new object[] { codeListView.Items }); Debug.WriteLine("Select All cmd: " + (DateTime.Now - start).TotalMilliseconds + " ms"); } private void RecentProjectCmd_Executed(object sender, ExecutedRoutedEventArgs e) { if (!int.TryParse((string)e.Parameter, out int recentIndex) || recentIndex < 0 || recentIndex >= MainController.MAX_RECENT_PROJECTS) { throw new Exception("Bad parameter: " + e.Parameter); } Debug.WriteLine("Recent project #" + recentIndex); mMainCtrl.OpenRecentProject(recentIndex); } private void CodeListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { //Debug.WriteLine("SEL: add " + e.AddedItems.Count + ", rem " + e.RemovedItems.Count); } } }