treectrl.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,196 行 · 第 1/5 页

CPP
2,196
字号
}

void wxTreeCtrl::AssignStateImageList(wxImageList *imageList)
{
    SetStateImageList(imageList);
    m_ownsImageListState = true;
}

size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
                                    bool recursively) const
{
    wxCHECK_MSG( item.IsOk(), 0u, wxT("invalid tree item") );

    TraverseCounter counter(this, item, recursively);
    return counter.GetCount() - 1;
}

// ----------------------------------------------------------------------------
// control colours
// ----------------------------------------------------------------------------

bool wxTreeCtrl::SetBackgroundColour(const wxColour &colour)
{
#if !wxUSE_COMCTL32_SAFELY
    if ( !wxWindowBase::SetBackgroundColour(colour) )
        return false;

    ::SendMessage(GetHwnd(), TVM_SETBKCOLOR, 0, colour.GetPixel());
#endif

    return true;
}

bool wxTreeCtrl::SetForegroundColour(const wxColour &colour)
{
#if !wxUSE_COMCTL32_SAFELY
    if ( !wxWindowBase::SetForegroundColour(colour) )
        return false;

    ::SendMessage(GetHwnd(), TVM_SETTEXTCOLOR, 0, colour.GetPixel());
#endif

    return true;
}

// ----------------------------------------------------------------------------
// Item access
// ----------------------------------------------------------------------------

wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
{
    wxCHECK_MSG( item.IsOk(), wxEmptyString, wxT("invalid tree item") );

    wxChar buf[512];  // the size is arbitrary...

    wxTreeViewItem tvItem(item, TVIF_TEXT);
    tvItem.pszText = buf;
    tvItem.cchTextMax = WXSIZEOF(buf);
    if ( !DoGetItem(&tvItem) )
    {
        // don't return some garbage which was on stack, but an empty string
        buf[0] = wxT('\0');
    }

    return wxString(buf);
}

void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
{
    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );

    if ( IS_VIRTUAL_ROOT(item) )
        return;

    wxTreeViewItem tvItem(item, TVIF_TEXT);
    tvItem.pszText = (wxChar *)text.c_str();  // conversion is ok
    DoSetItem(&tvItem);

    // when setting the text of the item being edited, the text control should
    // be updated to reflect the new text as well, otherwise calling
    // SetItemText() in the OnBeginLabelEdit() handler doesn't have any effect
    //
    // don't use GetEditControl() here because m_textCtrl is not set yet
    HWND hwndEdit = TreeView_GetEditControl(GetHwnd());
    if ( hwndEdit )
    {
        if ( item == m_idEdited )
        {
            ::SetWindowText(hwndEdit, text);
        }
    }
}

int wxTreeCtrl::DoGetItemImageFromData(const wxTreeItemId& item,
                                       wxTreeItemIcon which) const
{
    wxTreeViewItem tvItem(item, TVIF_PARAM);
    if ( !DoGetItem(&tvItem) )
    {
        return -1;
    }

    return ((wxTreeItemIndirectData *)tvItem.lParam)->GetImage(which);
}

void wxTreeCtrl::DoSetItemImageFromData(const wxTreeItemId& item,
                                        int image,
                                        wxTreeItemIcon which) const
{
    wxTreeViewItem tvItem(item, TVIF_PARAM);
    if ( !DoGetItem(&tvItem) )
    {
        return;
    }

    wxTreeItemIndirectData *data = ((wxTreeItemIndirectData *)tvItem.lParam);

    data->SetImage(image, which);

    // make sure that we have selected images as well
    if ( which == wxTreeItemIcon_Normal &&
         !data->HasImage(wxTreeItemIcon_Selected) )
    {
        data->SetImage(image, wxTreeItemIcon_Selected);
    }

    if ( which == wxTreeItemIcon_Expanded &&
         !data->HasImage(wxTreeItemIcon_SelectedExpanded) )
    {
        data->SetImage(image, wxTreeItemIcon_SelectedExpanded);
    }
}

void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item,
                                 int image,
                                 int imageSel)
{
    wxTreeViewItem tvItem(item, TVIF_IMAGE | TVIF_SELECTEDIMAGE);
    tvItem.iSelectedImage = imageSel;
    tvItem.iImage = image;
    DoSetItem(&tvItem);
}

int wxTreeCtrl::GetItemImage(const wxTreeItemId& item,
                             wxTreeItemIcon which) const
{
    wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") );

    if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
    {
        // TODO: Maybe a hidden root can still provide images?
        return -1;
    }

    if ( HasIndirectData(item) )
    {
        return DoGetItemImageFromData(item, which);
    }

    UINT mask;
    switch ( which )
    {
        default:
            wxFAIL_MSG( wxT("unknown tree item image type") );

        case wxTreeItemIcon_Normal:
            mask = TVIF_IMAGE;
            break;

        case wxTreeItemIcon_Selected:
            mask = TVIF_SELECTEDIMAGE;
            break;

        case wxTreeItemIcon_Expanded:
        case wxTreeItemIcon_SelectedExpanded:
            return -1;
    }

    wxTreeViewItem tvItem(item, mask);
    DoGetItem(&tvItem);

    return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage;
}

void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image,
                              wxTreeItemIcon which)
{
    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );

    if ( IS_VIRTUAL_ROOT(item) )
    {
        // TODO: Maybe a hidden root can still store images?
        return;
    }

    int imageNormal,
        imageSel;

    switch ( which )
    {
        default:
            wxFAIL_MSG( wxT("unknown tree item image type") );
            // fall through

        case wxTreeItemIcon_Normal:
            {
                const int imageNormalOld = GetItemImage(item);
                const int imageSelOld =
                    GetItemImage(item, wxTreeItemIcon_Selected);

                // always set the normal image
                imageNormal = image;

                // if the selected and normal images were the same, they should
                // be the same after the update, otherwise leave the selected
                // image as it was
                imageSel = imageNormalOld == imageSelOld ? image : imageSelOld;
            }
            break;

        case wxTreeItemIcon_Selected:
            imageNormal = GetItemImage(item);
            imageSel = image;
            break;

        case wxTreeItemIcon_Expanded:
        case wxTreeItemIcon_SelectedExpanded:
            if ( !HasIndirectData(item) )
            {
                // we need to get the old images first, because after we create
                // the wxTreeItemIndirectData GetItemXXXImage() will use it to
                // get the images
                imageNormal = GetItemImage(item);
                imageSel = GetItemImage(item, wxTreeItemIcon_Selected);

                // if it doesn't have it yet, add it
                wxTreeItemIndirectData *data = new
                    wxTreeItemIndirectData(this, item);

                // copy the data to the new location
                data->SetImage(imageNormal, wxTreeItemIcon_Normal);
                data->SetImage(imageSel, wxTreeItemIcon_Selected);
            }

            DoSetItemImageFromData(item, image, which);

            // reset the normal/selected images because we won't use them any
            // more - now they're stored inside the indirect data
            imageNormal =
            imageSel = I_IMAGECALLBACK;
            break;
    }

    // NB: at least in version 5.00.0518.9 of comctl32.dll we need to always
    //     change both normal and selected image - otherwise the change simply
    //     doesn't take place!
    DoSetItemImages(item, imageNormal, imageSel);
}

wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
{
    wxCHECK_MSG( item.IsOk(), NULL, wxT("invalid tree item") );

    wxTreeViewItem tvItem(item, TVIF_PARAM);

    // Hidden root may have data.
    if ( IS_VIRTUAL_ROOT(item) )
    {
        return GET_VIRTUAL_ROOT()->GetData();
    }

    // Visible node.
    if ( !DoGetItem(&tvItem) )
    {
        return NULL;
    }

    wxTreeItemData *data = (wxTreeItemData *)tvItem.lParam;
    if ( IsDataIndirect(data) )
    {
        data = ((wxTreeItemIndirectData *)data)->GetData();
    }

    return data;
}

void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data)
{
    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );

    if ( IS_VIRTUAL_ROOT(item) )
    {
        GET_VIRTUAL_ROOT()->SetData(data);
    }

    // first, associate this piece of data with this item
    if ( data )
    {
        data->SetId(item);
    }

    wxTreeViewItem tvItem(item, TVIF_PARAM);

    if ( HasIndirectData(item) )
    {
        if ( DoGetItem(&tvItem) )
        {
            ((wxTreeItemIndirectData *)tvItem.lParam)->SetData(data);
        }
        else
        {
            wxFAIL_MSG( wxT("failed to change tree items data") );
        }
    }
    else
    {
        tvItem.lParam = (LPARAM)data;
        DoSetItem(&tvItem);
    }
}

void wxTreeCtrl::SetIndirectItemData(const wxTreeItemId& item,
                                     wxTreeItemIndirectData *data)
{
    // this should never happen because it's unnecessary and will probably lead
    // to crash too because the code elsewhere supposes that the pointer the
    // wxTreeItemIndirectData has is a real wxItemData and not
    // wxTreeItemIndirectData as well
    wxASSERT_MSG( !HasIndirectData(item), wxT("setting indirect data twice?") );

    SetItemData(item, data);
}

bool wxTreeCtrl::HasIndirectData(const wxTreeItemId& item) const
{
    // query the item itself
    wxTreeViewItem tvItem(item, TVIF_PARAM);
    if ( !DoGetItem(&tvItem) )
    {
        return false;
    }

    wxTreeItemData *data = (wxTreeItemData *)tvItem.lParam;

    return data && IsDataIndirect(data);
}

void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
{
    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );

    if ( IS_VIRTUAL_ROOT(item) )
        return;

    wxTreeViewItem tvItem(item, TVIF_CHILDREN);
    tvItem.cChildren = (int)has;
    DoSetItem(&tvItem);
}

void wxTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
{
    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );

    if ( IS_VIRTUAL_ROOT(item) )
        return;

    wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_BOLD);
    tvItem.state = bold ? TVIS_BOLD : 0;
    DoSetItem(&tvItem);
}

void wxTreeCtrl::SetItemDropHighlight(const wxTreeItemId& item, bool highlight)
{
    if ( IS_VIRTUAL_ROOT(item) )
        return;

    wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_DROPHILITED);
    tvItem.state = highlight ? TVIS_DROPHILITED : 0;
    DoSetItem(&tvItem);
}

void wxTreeCtrl::RefreshItem(const wxTreeItemId& item)
{
    if ( IS_VIRTUAL_ROOT(item) )
        return;

    wxRect rect;
    if ( GetBoundingRect(item, rect) )
    {
        RefreshRect(rect);
    }
}

wxColour wxTreeCtrl::GetItemTextColour(const wxTreeItemId& item) const
{
    wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") );

    wxMapTreeAttr::const_iterator it = m_attrs.find(item.m_pItem);
    return it == m_attrs.end() ? wxNullColour : it->second->GetTextColour();
}

wxColour wxTreeCtrl::GetItemBackgroundColour(const wxTreeItemId& item) const
{
    wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") );

    wxMapTreeAttr::const_iterator it = m_attrs.find(item.m_pItem);
    return it == m_attrs.end() ? wxNullColour : it->second->GetBackgroundColour();
}

wxFont wxTreeCtrl::GetItemFont(const wxTreeItemId& item) const
{
    wxCHECK_MSG( item.IsOk(), wxNullFont, wxT("invalid tree item") );

    wxMapTreeAttr::const_iterator it = m_attrs.find(item.m_pItem);
    return it == m_attrs.end() ? wxNullFont : it->second->GetFont();
}

void wxTreeCtrl::SetItemTextColour(const wxTreeItemId& item,
                                   const wxColour& col)
{
    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );

    wxTreeItemAttr *attr;
    wxMapTreeAttr::iterator it = m_attrs.find(item.m_pItem);
    if ( it == m_attrs.end() )
    {
        m_hasAnyAttr = true;

        m_attrs[item.m_pItem] =
        attr = new wxTreeItemAttr;
    }
    else
    {
        attr = it->second;
    }

    attr->SetTextColour(col);

    RefreshItem(item);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?