コード例 #1
0
        /// <summary>
        /// This method should be call when you want to load the xml files which don't have a corresponding gif file
        /// of the same name. This method is actually called by the method wich load all the gif of a folder, as a second pass.
        /// </summary>
        /// <param name="buildingInfo">The building info, mainly used to store the group encountered</param>
        /// <param name="xmlFiles">The list of xml file to load</param>
        /// <param name="xmlFileUnloadable">a list to store the errors when some file cannot be loaded</param>
        private void fillListViewWithPartsWithoutImage(CategoryBuildingInfo buildingInfo, List<FileInfo> xmlFiles, List<FileNameWithException> xmlFileUnloadable, bool allowReplacement)
        {
            // iterate on the array of xmlFiles
            foreach (FileInfo file in xmlFiles)
            {
                try
                {
                    // get the name without extension and use upper case
                    string name = file.Name.Substring(0, file.Name.Length - 4).ToUpperInvariant();

                    // add the brick in the library
                    BrickLibrary.Brick brickAdded = BrickLibrary.Instance.AddBrick(name, null, file.FullName, allowReplacement);

                    // if the image is a group, add it to the group list
                    if (brickAdded.IsAGroup)
                        buildingInfo.mGroupList.Add(brickAdded);
                }
                catch (Exception e)
                {
                    // add the file that can't be loaded in the list of problems
                    xmlFileUnloadable.Add(new FileNameWithException(file.FullName, e.Message));
                }
            }
        }
コード例 #2
0
        private void fillListViewWithGroups(CategoryBuildingInfo buildingInfo, List<FileNameWithException> imageFileUnloadable, List<FileNameWithException> xmlFileUnloadable)
        {
            // start the begin update outside of the loop because on Mono it's very slow to add items in the list view
            buildingInfo.mListView.BeginUpdate();

            // do a third pass to generate and add the group parts in the library
            // we need to do it in a third pass in order to have read all the group xml files
            foreach (BrickLibrary.Brick group in buildingInfo.mGroupList)
            {
                try
                {
                    // generate the image for the group
                    BrickLibrary.Instance.createGroupImage(group);
                    // add this brick in the list view
                    addOnePartInListView(buildingInfo, group);
                }
                catch (Exception e)
                {
                    // add the group that can't be loaded in the list of problems (cyclic group for example)
                    xmlFileUnloadable.Add(new FileNameWithException(group.mPartNumber + ".xml", e.Message));
                }
            }

            // resume the update
            buildingInfo.mListView.EndUpdate();
        }
コード例 #3
0
        private void fillListViewWithParts(CategoryBuildingInfo buildingInfo, DirectoryInfo folder, List<FileNameWithException> imageFileUnloadable, List<FileNameWithException> xmlFileUnloadable)
        {
            // start the begin update outside of the loop because on Mono it's very slow to add items in the list view
            buildingInfo.mListView.BeginUpdate();

            // get the list of xml and image in the folder
            List<FileInfo> xmlFiles = new List<FileInfo>(folder.GetFiles("*.xml"));
            FileInfo[] imageFiles = folder.GetFiles("*.gif");
            // then iterate on all the images
            foreach (FileInfo file in imageFiles)
            {
                try
                {
                    // read the image from the file
                    Bitmap image = new Bitmap(file.FullName);

                    // construct the XML file
                    string xmlFileName = file.FullName.Substring(0, file.FullName.Length - 3) + "xml";

                    try
                    {
                        // get the name without extension and use upper case
                        string name = file.Name.Substring(0, file.Name.Length - 4).ToUpperInvariant();

                        // remove the xml file name from the list first because we don't want to try to load
                        // it a second time if an exception is raised.
                        foreach (FileInfo xmlFileInfo in xmlFiles)
                            if (xmlFileInfo.FullName.Equals(xmlFileName))
                            {
                                xmlFiles.Remove(xmlFileInfo);
                                break;
                            }

                        // put the image in the database
                        BrickLibrary.Brick brick = BrickLibrary.Instance.AddBrick(name, image, xmlFileName, false);

                        // add this part into the listview
                        addOnePartInListView(buildingInfo, brick);
                    }
                    catch (Exception e)
                    {
                        // add the file that can't be loaded in the list of problems
                        xmlFileUnloadable.Add(new FileNameWithException(xmlFileName, e.Message));
                    }
                }
                catch (Exception e)
                {
                    // add the file that can't be loaded in the list of problems
                    imageFileUnloadable.Add(new FileNameWithException(file.FullName, e.Message));
                }
            }

            // resume the update
            buildingInfo.mListView.EndUpdate();

            // now check if there's xml files without GIF. In that case we still load them but these
            // parts will be ignored by BlueBrick
            fillListViewWithPartsWithoutImage(buildingInfo, xmlFiles, xmlFileUnloadable, false);
        }
コード例 #4
0
 private void fillListViewWithGroupAndImageToFinalize(CategoryBuildingInfo buildingInfo, List<FileNameWithException> imageFileUnloadable, List<FileNameWithException> xmlFileUnloadable)
 {
     // then add the group parts in the list view. We need to do it after parsing the whole library
     // because a group part can reference any part in any folder
     fillListViewWithGroups(buildingInfo, imageFileUnloadable, xmlFileUnloadable);
     // then fill the list view (we cannot pass the building info as parameter because this function is called elsewhere)
     fillListViewWithImageList(buildingInfo.mListView, buildingInfo.mImageList, buildingInfo.mRespectProportion);
     // refilter the list view after we added all the parts (that will also sort the list)
     buildingInfo.mListView.refilter(true);
 }
コード例 #5
0
        /// <summary>
        /// This method create a new TabPage into the tab control of the library panel, and also create the ListView
        /// that holds the brick items, which is the only child of the TabPage
        /// </summary>
        /// <param name="buildingInfo">The building info that can be used to create the tab</param>
        /// <param name="tabPageName">The name of the tab page (which should be the name of the folder)</param>
        /// <param name="displaySetting">a display setting to correctly init the tab properties</param>
        private void addOneTabPageWithItsListView(CategoryBuildingInfo buildingInfo, string tabPageName, PartLibDisplaySetting displaySetting)
        {
            // add the tab in the tab control, based on the name of the folder
            TabPage newTabPage = new TabPage(tabPageName);
            newTabPage.Name = tabPageName;
            newTabPage.ContextMenuStrip = createContextMenuItemForATabPage(displaySetting.mLargeIcons, displaySetting.mRespectProportion);
            this.TabPages.Add(newTabPage);

            // then for the new tab added, we add a list control to
            // fill it with the pictures found in that folder
            // but we don't need to create it, we use the one created in the building info
            PartListView newListView = buildingInfo.mListView; // get a shortcut on the list view
            // filter the view (at this point it will be useless since there's no item in the view, but the goal is to save the filter sentence, it will be refilter later)
            newListView.filter(displaySetting.mFilterSentence, true);
            // set the tile size
            if (displaySetting.mLargeIcons)
                newListView.TileSize = PART_ITEM_LARGE_SIZE_WITH_MARGIN;
            else
                newListView.TileSize = PART_ITEM_SMALL_SIZE_WITH_MARGIN;
            // set the event handler
            newListView.MouseMove += new System.Windows.Forms.MouseEventHandler(this.listView_MouseMove);

            // add the list view to the tab page
            newTabPage.Controls.Add(newListView);
        }
コード例 #6
0
        private void addOnePartInListView(CategoryBuildingInfo buildingInfo, BrickLibrary.Brick brick)
        {
            // add the brick in library if we should do it
            if (!brick.NotListedInLibrary)
            {
                int imageIndex = buildingInfo.mImageList.Count;

                // add the image in the image list (after using the imageList.Count, but before creating the item,
                // otherwise mono is not happy cause it tries to access the image while creating the item)
                buildingInfo.mImageList.Add(brick.Image);

                // create a new item for the list view item
                ListViewItem newItem = new ListViewItem(null as string, imageIndex);
                newItem.ToolTipText = BrickLibrary.Instance.getFormatedBrickInfo(brick.mPartNumber,
                                                            Settings.Default.PartLibBubbleInfoPartID,
                                                            Settings.Default.PartLibBubbleInfoPartColor,
                                                            Settings.Default.PartLibBubbleInfoPartDescription);

                // set the tag to the item
                newItem.Tag = brick.mPartNumber;
                // also set the name to allow the sorting of the part
                // we could have use the Text property and the Sorting property of the listview, but the stupid
                // listview display the Text in the bubble info even when ShowToolTips is false.
                // also concatenate the sorting key with the part number such as we always have a fix order,
                // even after several filtering and even if the sorting key is not set. But if it is set,
                // the sorting key has the priority since it is place in front
                newItem.Name = BrickLibrary.Instance.getSortingKey(brick.mPartNumber) + brick.mPartNumber;
                // the text is used to display the count and budget
                newItem.Text = Budget.Budget.Instance.getCountAndBudgetAsString(brick.mPartNumber);

                // and insert the item
                buildingInfo.mListView.addNewItem(newItem);
            }
        }
コード例 #7
0
        /// <summary>
        /// This function should be called when you want to load more files after the loading of the library is finished.
        /// This function is mainly called when the user save a new group in the library. This function will not delete any
        /// part, but will update the existing part if you reload the same part.
        /// </summary>
        /// <param name="xmlFiles">The list of group xml to load</param>
        public void loadAdditionnalGroups(List<FileInfo> xmlFiles, List<string> groupNames)
        {
            // use a default display setting that won't be used to change the setting of the Custom tab page
            // unless this tab page doesn't exist, in which case the default setting is suitable
            PartLibDisplaySetting displaySetting = new PartLibDisplaySetting();
            CategoryBuildingInfo buildingInfo = new CategoryBuildingInfo(displaySetting.mRespectProportion);

            // first check if the Custom tab exits. If not we need to create it.
            if (this.TabPages.ContainsKey(PartLibraryPanel.sFolderNameForCustomParts))
            {
                // the tabe page exist, so get it
                TabPage tabPage = this.TabPages[this.TabPages.IndexOfKey(PartLibraryPanel.sFolderNameForCustomParts)];
                // patch the building info with the correct listview
                buildingInfo.mListView = tabPage.Controls[0] as PartListView;
                // patch also the image list
                buildingInfo.mImageList = buildingInfo.mListView.reconstructImageListFromBrickLibrary();
                // patch the respect proportion
                buildingInfo.mRespectProportion = (tabPage.ContextMenuStrip.Items[(int)ContextMenuIndex.RESPECT_PROPORTION] as ToolStripMenuItem).Checked;

                // now check if the part is already in, and remove it in order to replace it
                foreach (string name in groupNames)
                    foreach (ListViewItem item in buildingInfo.mListView.Items)
                        if (item.Tag.Equals(name))
                        {
                            int removedImageIndex = item.ImageIndex;
                            buildingInfo.mImageList.RemoveAt(removedImageIndex);
                            buildingInfo.mListView.Items.Remove(item);
                            // then iterate again on all the item to shift all the image index that are after the item removed of -1
                            foreach (ListViewItem itemToShift in buildingInfo.mListView.Items)
                                if (itemToShift.ImageIndex > removedImageIndex)
                                    itemToShift.ImageIndex = itemToShift.ImageIndex - 1;
                            // break the list view search since we found the item to remove
                            break;
                        }
            }
            else
            {
                // The custom page doesn't exist we need to create a new one
                addOneTabPageWithItsListView(buildingInfo, PartLibraryPanel.sFolderNameForCustomParts, displaySetting);
            }

            // now load the xml files
            List<FileNameWithException> imageFileUnloadable = new List<FileNameWithException>();
            List<FileNameWithException> xmlFileUnloadable = new List<FileNameWithException>();
            fillListViewWithPartsWithoutImage(buildingInfo, xmlFiles, xmlFileUnloadable, true);

            // the fill the list view with the new groups
            fillListViewWithGroupAndImageToFinalize(buildingInfo, imageFileUnloadable, xmlFileUnloadable);

            // after the loading is finished eventually display the error messages
            displayErrorMessage(imageFileUnloadable, xmlFileUnloadable);

            // Select the Custom Tab page
            int cutsomTabIndex = this.TabPages.IndexOfKey(PartLibraryPanel.sFolderNameForCustomParts);
            if (cutsomTabIndex >= 0)
            {
                // select the Custom tab
                this.SelectTab(cutsomTabIndex);
                // find the first item created and scroll it in view
                foreach (ListViewItem item in buildingInfo.mListView.Items)
                    if (item.Tag.Equals(groupNames[0]))
                    {
                        buildingInfo.mListView.EnsureVisible(item.Index);
                        break;
                    }
            }
        }
コード例 #8
0
        /// <summary>
        /// parse the part folder to find all the part in the library
        /// </summary>
        public void initPartsTabControl()
        {
            // suspend layout when rebuilding the library
            this.SuspendLayout();

            // init the part tab control based on the folders found on the drive
            // first clear the tab control
            this.TabPages.Clear();
            // then search the "parts" folder, if not here maybe we should display
            // an error message (something wrong with the installation of the application?)
            DirectoryInfo partsFolder = new DirectoryInfo(PartLibraryPanel.sFullPathForLibrary);
            if (partsFolder.Exists)
            {
                // create two list to record the exception thrown by some files
                List<FileNameWithException> imageFileUnloadable = new List<FileNameWithException>();
                List<FileNameWithException> xmlFileUnloadable = new List<FileNameWithException>();

                // create from the Settings a dictionary to store the display status of each tab
                Dictionary<string, PartLibDisplaySetting> tabDisplayStatus = new Dictionary<string,PartLibDisplaySetting>();
                foreach (string tabConfig in Settings.Default.UIPartLibDisplayConfig)
                {
                    // the format of the tabConfig string is: tabName00?filterSentence
                    // we will split it in the middle at the '?' char
                    string filterSentence = string.Empty;
                    // get the index of the ? character which is the separator between the tab name and the filter keywords
                    // because the ? char cannot be used in filename (and tab name comes from filename)
                    int separatorIndex = tabConfig.IndexOf('?');
                    if (separatorIndex < 0)
                        separatorIndex = tabConfig.Length; // check the case of old config file without "?" char separator
                    // get the first part before the keyword
                    string tabNameAndDisplayConfig = tabConfig.Substring(0, separatorIndex);
                    // maybe we have some keywords, so try to get them
                    if (tabConfig.Length > separatorIndex + 1)
                        filterSentence = tabConfig.Substring(separatorIndex + 1);
                    tabDisplayStatus.Add(tabNameAndDisplayConfig.Remove(separatorIndex - 2),
                                         new PartLibDisplaySetting(tabNameAndDisplayConfig[separatorIndex - 2] == '1',
                                                                    tabNameAndDisplayConfig[separatorIndex - 1] == '1',
                                                                    filterSentence));
                }

                // get all the folders in the parts folder to create a tab for each folder found
                DirectoryInfo[] categoryFolder = partsFolder.GetDirectories();

                // create a list to store all the info necessary for the library building for each category
                List<CategoryBuildingInfo> categoryList = new List<CategoryBuildingInfo>(categoryFolder.Length);

                // iterate on each folder
                foreach (DirectoryInfo category in categoryFolder)
                {
                    // try to get the display setting or construct a default one
                    PartLibDisplaySetting displaySetting = null;
                    if (!tabDisplayStatus.TryGetValue(category.Name, out displaySetting))
                        displaySetting = new PartLibDisplaySetting();

                    // create a building info and add it to the list
                    CategoryBuildingInfo buildingInfo = new CategoryBuildingInfo(displaySetting.mRespectProportion);
                    categoryList.Add(buildingInfo);

                    // create the tab page corresponding to the folder
                    addOneTabPageWithItsListView(buildingInfo, category.Name, displaySetting);

                    // fill the list view with the parts loaded from the files
                    fillListViewWithParts(buildingInfo, category, imageFileUnloadable, xmlFileUnloadable);
                }

                // reiterate on a second pass on all the list view, because we need to add the group parts
                foreach (CategoryBuildingInfo buildingInfo in categoryList)
                {
                    fillListViewWithGroupAndImageToFinalize(buildingInfo, imageFileUnloadable, xmlFileUnloadable);
                }

                // after the loading is finished eventually display the error messages
                displayErrorMessage(imageFileUnloadable, xmlFileUnloadable);

                // after creating all the tabs, sort them according to the settings
                updateAppearanceAccordingToSettings(true, false, false, false, true, true);

                // call the index event handler manually cause, it is not called on Mono
                PartLibraryPanel_SelectedIndexChanged(null, null);
            }

            // suspend layout when rebuilding the library
            this.ResumeLayout();
        }