/// <summary>
        /// Returns the listview for a given section. If it does not exist yet it gets created.
        /// Optionally a simple panel is added as header for this section.
        /// </summary>
        private ListView GetSectionListview(NodeIdWrapper controlNodeId, CollapsingPanel overviewPanel, bool addSectionHeader,
            Overview.DisplayMode displayMode, String caption, String info)
        {
            // Iterate over all sections we have already and find the one with the given control id.
              String objectId = wbOverview.get_node_unique_id(controlNodeId);
              foreach (Control control in overviewPanel.Controls)
              {
            if (control.Tag != null)
            {
              String currentObjectId = (control.Tag as Identifier).objectId;
              if (currentObjectId != null && currentObjectId == objectId)
              {
            ListView listview = control as ListView;
            SetViewMode(listview, displayMode);
            return listview;
              }
            }
              }

              // If we come here then the section does not exist yet, so add it. Start with a header.
              if (addSectionHeader)
              {
            Panel panel = new Panel();
            panel.BorderStyle = BorderStyle.None;
            panel.Padding = new Padding(5, 2, 5, 0);
            panel.BackgroundImage = Resources.header_bar_blue;
            panel.BackgroundImageLayout = ImageLayout.None;

            panel.Height = 24;

            // Insert client controls in reverse order.
            // Info label.
            Label infoLabel = new Label();
            infoLabel.Text = info;
            infoLabel.ForeColor = Color.Gray;
            infoLabel.Font = overviewPanel.Font;
            infoLabel.AutoSize = true;
            infoLabel.Margin = new Padding(10, 0, 0, 0);
            infoLabel.Dock = DockStyle.Left;
            panel.Controls.Add(infoLabel);

            overviewPanel.Controls.Add(panel);

            // Caption label.
            Label captionLabel = new Label();
            captionLabel.Text = caption;
            //captionLabel.Font = new Font(overviewPanel.Font, FontStyle.Bold);
            captionLabel.AutoSize = true;
            captionLabel.Dock = DockStyle.Left;
            captionLabel.ForeColor = Color.Black;
            panel.Controls.Add(captionLabel);

            overviewPanel.Controls.Add(panel);
              }

              // Then the content view.
              ListView sectionListview = new ListView();
              sectionListview.BorderStyle = BorderStyle.None;
              sectionListview.AllowColumnReorder = true;
              sectionListview.ShowItemToolTips = true;

              // Undocumented feature: enabling AutoSize will indeed make the control automatically resize
              // (the docs say it wouldn't) though without considering long captions. For them to work
              // additionally Scrollable can be set to true to show a scrollbar, but only in this special case.
              sectionListview.AutoSize = true;
              sectionListview.MultiSelect = false;
              sectionListview.Scrollable = true;
              sectionListview.Visible = true;
              sectionListview.Font = overviewPanel.Font;
              sectionListview.Tag = CreateIdentifier(controlNodeId);
              sectionListview.Sorting = SortOrder.None; // We do custom sort.

              sectionListview.DoubleClick += new EventHandler(listViewDoubleClick);
              sectionListview.ItemDrag += new ItemDragEventHandler(listViewItemDrag);
              sectionListview.SelectedIndexChanged += new EventHandler(listViewSelectedIndexChanged);
              sectionListview.KeyDown += new KeyEventHandler(listViewKeyDown);
              sectionListview.MouseUp += new MouseEventHandler(listViewMouseUp);
              sectionListview.ColumnClick += new ColumnClickEventHandler(ListviewColumnClick);
              sectionListview.Enter += new EventHandler(ListViewEnter);

              // Renaming of overview nodes
              sectionListview.LabelEdit = true;
              sectionListview.AfterLabelEdit += new LabelEditEventHandler(listViewAfterLabelEdit);
              sectionListview.BeforeLabelEdit += new LabelEditEventHandler(listViewBeforeLabelEdit);

              // Add it to the panel. Usually the layout engine of the panel should take care for
              // the layout of the controls, but just to be sure we set here a dock style.
              overviewPanel.Controls.Add(sectionListview);
              sectionListview.Dock = DockStyle.Top;

              // Set Image Lists
              sectionListview.SmallImageList = IconManagerWrapper.ImageList16;
              sectionListview.LargeImageList = IconManagerWrapper.ImageList48;

              SetViewMode(sectionListview, displayMode);

              sectionListview.Update();
              return sectionListview;
        }
        /// <summary>
        /// Returns the current view mode of the listview that represents the content of the given panel.
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private View GetViewMode(CollapsingPanel panel)
        {
            foreach (Control control in panel.Controls)
            if (control is ListView)
              return (control as ListView).View;

              return View.LargeIcon;
        }
        private void FillPanelContent(NodeIdWrapper panelNodeId, Overview.DisplayMode displayMode, CollapsingPanel overviewPanel)
        {
            // Check the node type of the child items
              int itemNodeType;
              wbOverview.get_field(panelNodeId, (int)Overview.Columns.ChildNodeType, out itemNodeType);

              switch ((Overview.NodeType)itemNodeType)
              {
            case Overview.NodeType.Group:
              {
            // If the child items are of type Group, add them as tabs.
            EnableTabViewForPanel(displayMode, overviewPanel);

            // Fill child items
            if (wbOverview.count_children(panelNodeId) > 0)
              FillPanelContent(wbOverview.get_child(panelNodeId, 0), currentOverviewDisplayMode, overviewPanel);
              }
              break;
            case Overview.NodeType.Section:
              // If they are of item type Section populate the list view with sections and items.
              PopulateSections(overviewPanel, displayMode, true);
              break;
            case Overview.NodeType.Item:
              {
            // If the child entry is an item thean we don't have any intermediate structure.
            ListView sectionListview = GetSectionListview(panelNodeId, overviewPanel, false, displayMode, "", "");
            cacheListview(panelNodeId.toString(), sectionListview);
            PopulateListView(panelNodeId, sectionListview);
            break;
              }
              }
        }
        /// <summary>
        /// Sets the given panel up so that it shows tabs on top that can be used to switch content.
        /// </summary>
        /// <param name="displayMode"></param>
        /// <param name="overviewPanel"></param>
        private void EnableTabViewForPanel(Overview.DisplayMode displayMode, CollapsingPanel overviewPanel)
        {
            overviewPanel.TabHeaderImageList = new ImageList();
              overviewPanel.TabHeaderImageList.ColorDepth = ColorDepth.Depth32Bit;
              overviewPanel.TabHeaderImageList.ImageSize = new Size(32, 32);

              overviewPanel.TabHeaderImageList = IconManagerWrapper.ImageList32;

              overviewPanel.DisplayMode = CollapsingPanelDisplayMode.HeaderAndTab;

              overviewPanel.TabCountNeeded += new TabCountHandler(overviewPanel_TabCountNeeded);
              overviewPanel.TabInfoNeeded += new TabInfoHandler(overviewPanel_TabInfoNeeded);
              overviewPanel.TabChanged += new TabChangedHandler(overviewPanel_TabChanged);
              overviewPanel.TabDoubleClicked += new MouseEventHandler(overviewPanel_TabDoubleClicked);
              overviewPanel.TabHeaderMouseUp += new MouseEventHandler(overviewPanel_TabHeaderMouseUp);

              // Select the first tab to populate the ListView
              overviewPanel.SelectedTabIndex = 0;

              overviewPanel.DisplayTabActionButtons = true;
              overviewPanel.TabAddButtonClicked += new EventHandler(overviewPanel_TabAddButtonClicked);
              overviewPanel.TabDelButtonClicked += new EventHandler(overviewPanel_TabDelButtonClicked);

              // Buttons for display mode.
              overviewPanel.DisplayCustomButtons = true;
              overviewPanel.CustomButtonClicked += new CustomButtonEvent(overviewPanel_CustomButtonClicked);

              overviewPanel.AddCustomButton(26, 23, "collapsing_panel_grid_large_icons",
            displayMode == Overview.DisplayMode.LargeIcon);
              overviewPanel.AddCustomButton(26, 23, "collapsing_panel_grid_small_icons",
            displayMode == Overview.DisplayMode.SmallIcon);
              overviewPanel.AddCustomButton(26, 23, "collapsing_panel_grid_details",
            displayMode == Overview.DisplayMode.List);
        }
        public void RebuildModelContents()
        {
            overviewInvalid = true;

              // Don't reload the entire page if we are just about to refresh it anyway.
              if (!states.ContainsKey(RefreshState.Schema))
              {
            scrollPanel.SuspendLayout();
            NodeIdWrapper rootNodeId = wbOverview.get_root();

            ResetDocument(true);

            int count = wbOverview.count_children(rootNodeId);
            for (int i = 0; i < count; i++)
            {
              NodeIdWrapper panelNodeId = wbOverview.get_child(rootNodeId, i);
              string caption;
              int expanded;
              Overview.DisplayMode displayMode;
              int temp;

              if (!wbOverview.get_field(panelNodeId, (int)Overview.Columns.Label, out caption))
            throw new Exception("Invalid node");
              wbOverview.get_field(panelNodeId, (int)Overview.Columns.Expanded, out expanded);
              //wbOverview.get_field(panelNodeId, (int)Overview.Columns.Height, out height);
              wbOverview.get_field(panelNodeId, (int)Overview.Columns.DisplayMode, out temp);
              displayMode = (Overview.DisplayMode)temp;
              bool isExpansionDisabled = wbOverview.is_expansion_disabled();
              bool initialExpandState = !isExpansionDisabled;

              CollapsingPanel overviewPanel = new CollapsingPanel(caption, CollapsingPanelDisplayMode.Normal,
            CollapsingPanelStyle.Flat, initialExpandState, 0);
              overviewPanel.DisableExpansionIcon = isExpansionDisabled;
              overviewPanel.HeaderFont = new Font("Tahoma", 9.75f, FontStyle.Bold);
              overviewPanel.Padding = new Padding(12, 4, 0, 0);
              overviewPanel.BackColor = Color.White;

              panelsByNode[panelNodeId.toString()] = overviewPanel;

              overviewPanel.Tag = CreateIdentifier(panelNodeId);

              // Add the collapsing panel to the form. Move every panel explicitly to the top position
              // (moving all others down one step) to make stacking working properly.
              scrollPanel.Controls.Add(overviewPanel);
              scrollPanel.Controls.SetChildIndex(overviewPanel, 0);
              overviewPanel.Dock = DockStyle.Top;

              // Add panel to the list of panels for this model type so it can be deleted later.
              panelList.Add(overviewPanel);

              // If this is the first panel then remove its header.
              // The parent header panel will provide one.
              if (panelList.Count == 1)
            overviewPanel.DisplayMode = CollapsingPanelDisplayMode.NoHeader;

              // Check if there are child items
              FillPanelContent(panelNodeId, displayMode, overviewPanel);
              overviewPanel.Expanded = expanded == 1;

              if (skipHeader)
              {
            overviewPanel.DisplayTabActionButtons = false;
            overviewPanel.DisplayCustomButtons = false;
            overviewPanel.DisplayMode = CollapsingPanelDisplayMode.TabsOnly;
              }
            }
            scrollPanel.ResumeLayout(true);
              }

              // Update immediately so we have a complete overview page while loading other content.
              Update();
        }
        private void SetViewMode(CollapsingPanel panel, Overview.DisplayMode mode)
        {
            foreach (Control control in panel.Controls)
            if (control is ListView)
              SetViewMode(control as ListView, mode);

              panel.PerformLayout();
        }
        /// <summary>
        /// Fills the given panel with a number of sections (simple panel + listview pair) per section
        /// entry in wbOverview.
        /// </summary>
        private void PopulateSections(CollapsingPanel overviewPanel, Overview.DisplayMode displayMode, bool setDefaultTabPage)
        {
            if (overviewPanel != null && overviewPanel.Tag != null)
              {
            overviewPanel.SuspendLayout();
            try
            {
              NodeIdWrapper parentNodeId = null;

              // If this panel has tabs, choose the NodeId of the selected tab as parent.
              if (overviewPanel.DisplayMode == CollapsingPanelDisplayMode.HeaderAndTab ||
            overviewPanel.DisplayMode == CollapsingPanelDisplayMode.TabsOnly)
              {
            // make sure the selected index is still valid
            int count = wbOverview.count_children((overviewPanel.Tag as Identifier).id);
            if (count > 0)
            {
              int default_tab_page_index = wbOverview.get_default_tab_page_index();
              if (setDefaultTabPage && default_tab_page_index != -1)
              {
                overviewPanel.SelectedTabIndex = default_tab_page_index;
              }
              else if (overviewPanel.SelectedTabIndex > count - 1)
              {
                if (count > 0)
                  overviewPanel.SelectedTabIndex = count - 1;
                else
                  overviewPanel.SelectedTabIndex = 0;
              }

              parentNodeId = wbOverview.get_child((overviewPanel.Tag as Identifier).id,
                overviewPanel.SelectedTabIndex);

              // reselect the tab
              wbOverview.focus_node(parentNodeId);
            }
            else
            {
              overviewPanel.SelectedTabIndex = 0;
              parentNodeId = null;
            }
              }
              else
            // If this panel has no tabs, choose the NodeId of the panel itself as parent
            if (overviewPanel.DisplayMode == CollapsingPanelDisplayMode.Normal)
              parentNodeId = (overviewPanel.Tag as Identifier).id;

              if (parentNodeId != null)
              {
            int itemCount = wbOverview.count_children(parentNodeId);
            if (itemCount > 0)
            {
              NodeIdWrapper itemNodeId = wbOverview.get_child(parentNodeId, 0);

              // Check the node type of the child items
              int nodeType;
              wbOverview.get_field(itemNodeId, (int)Overview.Columns.NodeType, out nodeType);

              // If the node type is secion, loop over all sections and add them
              if (nodeType == (int)Overview.NodeType.Section)
              {
                for (int i = 0; i < itemCount; i++)
                {
                  NodeIdWrapper sectionNodeId = wbOverview.get_child(parentNodeId, i);

                  string caption;
                  wbOverview.get_field(sectionNodeId, (int)Overview.Columns.Label, out caption);

                  // Determine child count for info display but don't consider the default entry.
                  int childCount = wbOverview.count_children(sectionNodeId) - 1;
                  String info = "(" + childCount + ((childCount == 1) ? " item" : " items") + ")";
                  ListView sectionListview = GetSectionListview(sectionNodeId, overviewPanel, true, displayMode, caption, info);

                  cacheListview(sectionNodeId.toString(), sectionListview);

                  PopulateListViewColumns(sectionNodeId, sectionListview, displayMode);

                  PopulateListView(sectionNodeId, sectionListview);

                  if (sectionListview.View == View.Details)
                    RestoreColumnStates(sectionListview);
                }
              }
              else
              {
                // If there are no sections, simple add the items.
                ListView sectionListview = GetSectionListview(parentNodeId, overviewPanel, false, displayMode, "", "");
                cacheListview(parentNodeId.toString(), sectionListview);
                PopulateListView(parentNodeId, sectionListview);
              }
            }
              }
            }
            finally
            {
              overviewPanel.ResumeLayout();
            }
              }
        }