Пример #1
0
        private static ListBoxItem GetVisibleCategory(ListBox parent, int startIndex, Key key)
        {
            if (parent.Equals(null))
            {
                return(null);
            }

            var index     = startIndex;
            var generator = parent.ItemContainerGenerator;
            var category  = generator.ContainerFromIndex(index) as ListBoxItem;

            while (category != null &&
                   !WpfUtilities.ChildOfType <Expander>(category, string.Empty).IsExpanded)
            {
                if (key == Key.Down)
                {
                    index++;
                }
                if (key == Key.Up)
                {
                    index--;
                }

                if (0 <= index && index < parent.Items.Count)
                {
                    category = generator.ContainerFromIndex(index) as ListBoxItem;
                }
                else
                {
                    category = null;
                }
            }

            return(category);
        }
Пример #2
0
        private ListBoxItem FindChildListItemByIndex(FrameworkElement parent, string listName, int index = 0)
        {
            var list      = WpfUtilities.ChildOfType <ListBox>(parent, listName);
            var generator = list.ItemContainerGenerator;

            if (0 <= index && index < list.Items.Count)
            {
                return(generator.ContainerFromIndex(index) as ListBoxItem);
            }
            else
            {
                return(null);
            }
        }
Пример #3
0
        private ListBoxItem FindFirstVisibleCategory(FrameworkElement librarySearchViewElement)
        {
            var firstCategory = FindChildListItemByIndex(librarySearchViewElement, "CategoryListView");

            int index = 1;

            while (firstCategory != null &&
                   !WpfUtilities.ChildOfType <Expander>(firstCategory, string.Empty).IsExpanded)
            {
                firstCategory = FindChildListItemByIndex(librarySearchViewElement, "CategoryListView", index);
                index++;
            }

            return(firstCategory);
        }
Пример #4
0
        void DynamoViewModelRequestSaveImage(object sender, ImageSaveEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Path))
            {
                var control = WpfUtilities.ChildOfType <DragCanvas>(this, null);

                double width  = 1;
                double height = 1;

                // connectors are most often within the bounding box of the nodes and notes

                foreach (NodeModel n in dynamoViewModel.Model.CurrentWorkspace.Nodes)
                {
                    width  = Math.Max(n.X + n.Width, width);
                    height = Math.Max(n.Y + n.Height, height);
                }

                foreach (NoteModel n in dynamoViewModel.Model.CurrentWorkspace.Notes)
                {
                    width  = Math.Max(n.X + n.Width, width);
                    height = Math.Max(n.Y + n.Height, height);
                }

                var rtb = new RenderTargetBitmap(Math.Max(1, (int)width),
                                                 Math.Max(1, (int)height),
                                                 96,
                                                 96,
                                                 PixelFormats.Default);

                rtb.Render(control);

                //endcode as PNG
                var pngEncoder = new PngBitmapEncoder();
                pngEncoder.Frames.Add(BitmapFrame.Create(rtb));

                try
                {
                    using (var stm = File.Create(e.Path))
                    {
                        pngEncoder.Save(stm);
                    }
                }
                catch
                {
                    dynamoViewModel.Model.Logger.Log("Failed to save the Workspace an image.");
                }
            }
        }
Пример #5
0
        /// When a category is collapsed, the selection of underlying sub-category
        /// list is cleared. As a result any visible StandardPanel will be hidden.
        private void OnExpanderCollapsed(object sender, System.Windows.RoutedEventArgs e)
        {
            BringIntoViewCount++;
            var expanderContent = (sender as FrameworkElement);

            expanderContent.BringIntoView(new Rect(0.0, 0.0, 100.0, 20.0));

            var buttons = WpfUtilities.ChildOfType <ListView>(expanderContent);

            if (buttons != null)
            {
                buttons.UnselectAll();
            }

            e.Handled = true;
        }
Пример #6
0
        internal void SaveWorkspaceAsImage(string path)
        {
            var initialized = false;
            var bounds      = new Rect();

            double minX = 0.0, minY = 0.0;
            var    dragCanvas    = WpfUtilities.ChildOfType <DragCanvas>(this);
            var    childrenCount = VisualTreeHelper.GetChildrenCount(dragCanvas);

            for (int index = 0; index < childrenCount; ++index)
            {
                var child      = VisualTreeHelper.GetChild(dragCanvas, index);
                var firstChild = VisualTreeHelper.GetChild(child, 0);

                switch (firstChild.GetType().Name)
                {
                case "NodeView":
                case "NoteView":
                case "AnnotationView":
                    break;

                // Until we completely removed InfoBubbleView (or fixed its broken
                // size calculation), we will not be including it in our size
                // calculation here. This means that the info bubble, if any, will
                // still go beyond the boundaries of the final PNG file. I would
                // prefer not to add this hack here as it introduces multiple issues
                // (including NaN for Grid inside the view and the fix would be too
                // ugly to type in). Suffice to say that InfoBubbleView is not
                // included in the size calculation for screen capture (work-around
                // should be obvious).
                //
                // case "InfoBubbleView":
                //     child = WpfUtilities.ChildOfType<Grid>(child);
                //     break;

                // We do not take anything other than those above
                // into consideration when the canvas size is measured.
                default:
                    continue;
                }

                // Determine the smallest corner of all given visual elements on the
                // graph. This smallest top-left corner value will be useful in making
                // the offset later on.
                //
                var childBounds = VisualTreeHelper.GetDescendantBounds(child as Visual);
                minX          = childBounds.X < minX ? childBounds.X : minX;
                minY          = childBounds.Y < minY ? childBounds.Y : minY;
                childBounds.X = (double)(child as Visual).GetValue(Canvas.LeftProperty);
                childBounds.Y = (double)(child as Visual).GetValue(Canvas.TopProperty);

                if (initialized)
                {
                    bounds.Union(childBounds);
                }
                else
                {
                    initialized = true;
                    bounds      = childBounds;
                }
            }

            // Nothing found in the canvas, bail out.
            if (!initialized)
            {
                return;
            }

            // Add padding to the edge and make them multiples of two (pad 10px on each side).
            bounds.Width  = 20 + ((((int)Math.Ceiling(bounds.Width)) + 1) & ~0x01);
            bounds.Height = 20 + ((((int)Math.Ceiling(bounds.Height)) + 1) & ~0x01);

            var currentTransformGroup = WorkspaceElements.RenderTransform as TransformGroup;

            WorkspaceElements.RenderTransform = new TranslateTransform(10.0 - bounds.X - minX, 10.0 - bounds.Y - minY);
            WorkspaceElements.UpdateLayout();

            var rtb = new RenderTargetBitmap(((int)bounds.Width),
                                             ((int)bounds.Height), 96, 96, PixelFormats.Default);

            rtb.Render(WorkspaceElements);
            WorkspaceElements.RenderTransform = currentTransformGroup;

            try
            {
                using (var stm = System.IO.File.Create(path))
                {
                    // Encode as PNG format
                    var pngEncoder = new PngBitmapEncoder();
                    pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
                    pngEncoder.Save(stm);
                }
            }
            catch (Exception)
            {
            }
        }
Пример #7
0
        internal void SaveWorkspaceAsImage(string path)
        {
            var initialized = false;
            var bounds      = new Rect();

            var dragCanvas    = WpfUtilities.ChildOfType <DragCanvas>(this);
            var childrenCount = VisualTreeHelper.GetChildrenCount(dragCanvas);

            for (int index = 0; index < childrenCount; ++index)
            {
                var child      = VisualTreeHelper.GetChild(dragCanvas, index);
                var firstChild = VisualTreeHelper.GetChild(child, 0);
                if ((!(firstChild is NodeView)) && (!(firstChild is NoteView)) && (!(firstChild is AnnotationView)))
                {
                    continue;
                }

                var childBounds = VisualTreeHelper.GetDescendantBounds(child as Visual);
                childBounds.X = (double)(child as Visual).GetValue(Canvas.LeftProperty);
                childBounds.Y = (double)(child as Visual).GetValue(Canvas.TopProperty);

                if (initialized)
                {
                    bounds.Union(childBounds);
                }
                else
                {
                    initialized = true;
                    bounds      = childBounds;
                }
            }

            // Nothing found in the canvas, bail out.
            if (!initialized)
            {
                return;
            }

            // Add padding to the edge and make them multiples of two (pad 10px on each side).
            bounds.Width  = 20 + ((((int)Math.Ceiling(bounds.Width)) + 1) & ~0x01);
            bounds.Height = 20 + ((((int)Math.Ceiling(bounds.Height)) + 1) & ~0x01);

            var currentTransformGroup = WorkspaceElements.RenderTransform as TransformGroup;

            WorkspaceElements.RenderTransform = new TranslateTransform(10.0 - bounds.X, 10.0 - bounds.Y);
            WorkspaceElements.UpdateLayout();

            var rtb = new RenderTargetBitmap(((int)bounds.Width),
                                             ((int)bounds.Height), 96, 96, PixelFormats.Default);

            rtb.Render(WorkspaceElements);
            WorkspaceElements.RenderTransform = currentTransformGroup;

            try
            {
                using (var stm = System.IO.File.Create(path))
                {
                    // Encode as PNG format
                    var pngEncoder = new PngBitmapEncoder();
                    pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
                    pngEncoder.Save(stm);
                }
            }
            catch (Exception)
            {
            }
        }
Пример #8
0
        /// <summary>
        /// 'CategoryListView' element contains the following child elements (either
        /// directly, or indirectly nested): 'StackPanel', 'SubCategoryListView',
        /// 'MemberGroupsListBox' and 'MembersListBox'. If none of these child elements
        /// choose to process the key event, it gets bubbled up here. This typically
        /// happens for the following scenarios:
        ///
        /// 1. Down key is pressed when selection is on last entry of 'MembersListBox'
        /// 2. Up key is pressed when selection is on item on first row of 'SubCategoryListView'
        /// 3. Up key is pressed when selection is on the first entry of 'MembersListBox'
        ///    and there are no classes.
        ///
        /// </summary>
        private void OnCategoryKeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key != Key.Down) && (e.Key != Key.Up))
            {
                return;
            }

            // Selected member(in this scenario) can be only first/last member button or class button at the first row.
            var selectedMember        = HighlightedItem;
            var selectedMemberContext = selectedMember.DataContext as NodeSearchElementViewModel;
            var categoryListView      = sender as ListView;

            int categoryIndex = 0;

            for (int i = 0; i < categoryListView.Items.Count; i++)
            {
                var category = categoryListView.Items[i] as SearchCategory;
                if (category.ContainsClassOrMember(selectedMemberContext.Model))
                {
                    categoryIndex = i;
                    break;
                }
            }

            if (e.Key == Key.Down)
            {
                categoryIndex++;
            }
            if (e.Key == Key.Up)
            {
                categoryIndex--;
            }

            // The selection cannot be moved further up, returning here without handling the key event
            // so that parent visual element gets to handle it and move selection up to 'Top Result' list.
            if (categoryIndex < 0)
            {
                return;
            }
            // We are at the last member and there is no way to move down.
            if (categoryIndex >= categoryListView.Items.Count)
            {
                e.Handled = true;
                return;
            }

            var nextSelectedCategory = GetVisibleCategory(categoryListView, categoryIndex, e.Key);

            if (nextSelectedCategory == null)
            {
                e.Handled = e.Key == Key.Down;
                return;
            }

            if (e.Key == Key.Up)
            {
                var memberGroupsList = WpfUtilities.ChildOfType <ListBox>(nextSelectedCategory, "MemberGroupsListBox");
                var lastMemberGroup  = GetListItemByIndex(memberGroupsList, memberGroupsList.Items.Count - 1);
                var membersList      = WpfUtilities.ChildOfType <ListBox>(lastMemberGroup, "MembersListBox");

                // If key is up, then we have to select the last method button.
                UpdateHighlightedItem(GetListItemByIndex(membersList, membersList.Items.Count - 1));
            }
            else // Otherwise, Down was pressed, and we have to select first class/method button.
            {
#if SEARCH_SHOW_CLASSES
                if (nextselectedCategoryContent.Classes.Count > 0)
                {
                    // If classes are presented, then focus on first class.
                    FindFirstChildListItem(nextselectedCategory, "SubCategoryListView").Focus();
                }
                else
                {
                    // If there are no classes, then focus on first method.
                    var memberGroupsList = FindFirstChildListItem(nextselectedCategory, "MemberGroupsListBox");
                    FindFirstChildListItem(memberGroupsList, "MembersListBox").Focus();
                }
#else
                // If there are no classes, then focus on first method.
                var memberGroupsList = FindChildListItemByIndex(nextSelectedCategory, "MemberGroupsListBox");
                UpdateHighlightedItem(FindChildListItemByIndex(memberGroupsList, "MembersListBox"));
#endif
            }
            e.Handled = true;
        }
Пример #9
0
        // The 'StackPanel' that contains 'SubCategoryListView' and 'MemberGroupsListBox'
        // handles this message. If none of these two list boxes are handling the key
        // message, that means the currently selected list box item is the first/last item
        // in these two list boxes. When key message arrives here, it is then the 'StackPanel'
        // responsibility to move the selection on to the adjacent list box.
        private void OnCategoryContentKeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key != Key.Down) && (e.Key != Key.Up))
            {
                return;
            }

            // Selected member(in this scenario) can be only first/last member button or first/last class button.
            var selectedMember        = HighlightedItem as FrameworkElement;
            var searchCategoryElement = sender as FrameworkElement;

            // selectedMember is method button.
            if (selectedMember.DataContext is NodeSearchElementViewModel)
            {
                var searchCategoryContent = searchCategoryElement.DataContext as SearchCategory;

                // Gotten here because of last method being listed, pressing 'down' array cannot
                // move down further. Return here to allow higher level visual element to handle
                // the navigation (to a separate category).
                if (e.Key == Key.Down)
                {
                    return;
                }

                // Otherwise, pressed Key is Up.

#if SEARCH_SHOW_CLASSES
                // No class is found in this 'SearchCategory', return from here so that higher level
                // element gets to handle the navigational keys to move focus to the previous category.
                if (searchCategoryContent.Classes.Count == 0)
                {
                    return;
                }

                // Otherwise, we move to first class button.
                var listItem = FindFirstChildListItem(searchCategoryElement, "SubCategoryListView");
                if (listItem != null)
                {
                    listItem.Focus();
                }

                e.Handled = true;
#endif

                return;
            }

            // selectedMember is class button.
            if (selectedMember.DataContext is NodeCategoryViewModel)
            {
                // We are at the first row of class list. User presses up, we have to move to previous category.
                // We handle it further.
                if (e.Key == Key.Up)
                {
                    return;
                }

                // Otherwise user pressed down, we have to move to first member button.
                var memberGroupsListBox = WpfUtilities.ChildOfType <ListBox>(searchCategoryElement, "MemberGroupsListBox");
                var listItem            = FindChildListItemByIndex(memberGroupsListBox, "MembersListBox");
                if (listItem != null)
                {
                    UpdateHighlightedItem(listItem);
                }

                e.Handled = true;
                return;
            }
        }
Пример #10
0
        // This event is raised only, when we can't go down, to next member.
        // I.e. we are now at the last member button and we have to move to next member group.
        private void MemberGroupsKeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key != Key.Down) && (e.Key != Key.Up))
            {
                return;
            }

            var selectedMember     = HighlightedItem.DataContext as NodeSearchElementViewModel;
            var memberGroups       = (sender as ListBox).Items;
            var memberGroupListBox = sender as ListBox;

            int selectedMemberGroupIndex = 0;

            // Find out to which memberGroup selected member belong.
            for (int i = 0; i < memberGroups.Count; i++)
            {
                var memberGroup = memberGroups[i] as SearchMemberGroup;
                if (memberGroup.ContainsMember(selectedMember))
                {
                    selectedMemberGroupIndex = i;
                    break;
                }
            }

            int nextSelectedMemberGroupIndex = selectedMemberGroupIndex;

            // If user presses down, then we need to set focus to the next member group.
            // Otherwise to previous.
            if (e.Key == Key.Down)
            {
                nextSelectedMemberGroupIndex++;
            }
            if (e.Key == Key.Up)
            {
                nextSelectedMemberGroupIndex--;
            }

            // The member group list box does not attempt to process the key event if it
            // has moved beyond its available list of member groups. In this case, the
            // key event is considered not handled and will be left to the parent visual
            // (e.g. class button or another category) to handle.
            e.Handled = false;
            if (nextSelectedMemberGroupIndex < 0 || (nextSelectedMemberGroupIndex >= memberGroups.Count))
            {
                return;
            }

            var item = GetListItemByIndex(memberGroupListBox, nextSelectedMemberGroupIndex);
            var nextSelectedMembers = WpfUtilities.ChildOfType <ListBox>(item, "MembersListBox");

            // When moving on to the next member group list below (by pressing down arrow),
            // the focus should moved on to the first member in the member group list. Likewise,
            // when moving to the previous member group list above, the focus should be set on
            // the last member in that list.
            var itemIndex = 0;

            if (e.Key == Key.Up)
            {
                itemIndex = nextSelectedMembers.Items.Count - 1;
            }


            UpdateHighlightedItem(GetListItemByIndex(nextSelectedMembers, itemIndex));

            e.Handled = true;
        }
Пример #11
0
        private void OnLibraryWrapPanelKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            var classButton = Keyboard.FocusedElement as ListBoxItem;

            // Enter collapses and expands class button.
            if (e.Key == Key.Enter)
            {
                classButton.IsSelected = !classButton.IsSelected;
                e.Handled = true;
                return;
            }

            var buttonsWrapPanel = sender as LibraryWrapPanel;
            var listButtons      = buttonsWrapPanel.Children;

            // If focused element is NodeSearchElement, that means focused element is inside expanded class.
            if (classButton.DataContext is NodeSearchElement)
            {
                // If user presses Up, we have to move back to selected class.
                if (e.Key == Key.Up)
                {
                    var selectedClassButton = listButtons.OfType <ListViewItem>().
                                              Where(button => button.IsSelected).FirstOrDefault();
                    if (selectedClassButton != null)
                    {
                        selectedClassButton.Focus();
                    }
                    e.Handled = true;
                    return;
                }
                // Otherwise, let user move inside expanded class.
                return;
            }

            // If class is selected, we should move down to ClassDetails.
            else if (e.Key == Key.Down)
            {
                if (classButton.IsSelected)
                {
                    int classInfoIndex       = GetClassInformationIndex();
                    var classInformationView = listButtons[classInfoIndex];
                    var firstMemberList      = WpfUtilities.ChildOfType <ListBox>(classInformationView, "primaryMembers");
                    var generator            = firstMemberList.ItemContainerGenerator;
                    (generator.ContainerFromIndex(0) as ListBoxItem).Focus();

                    e.Handled = true;
                    return;
                }
            }

            var selectedIndex = listButtons.IndexOf(classButton);
            int itemsPerRow   = (int)Math.Floor(buttonsWrapPanel.ActualWidth / classButton.ActualWidth);

            int newIndex = GetIndexNextSelectedItem(e.Key, selectedIndex, itemsPerRow);

            // If index is out of range class list, that means we have to move to previous category
            // or to next member group.
            if ((newIndex < 0) || (newIndex > listButtons.Count))
            {
                e.Handled = false;
                return;
            }

            // Set focus on new item.
            listButtons[newIndex].Focus();

            e.Handled = true;
            return;
        }