treectlg.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,169 行 · 第 1/5 页
CPP
2,169 行
}
void wxGenericTreeCtrl::Unselect()
{
if (m_current)
{
m_current->SetHilight( false );
RefreshLine( m_current );
m_current = NULL;
m_select_me = NULL;
}
}
void wxGenericTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item)
{
if (item->IsSelected())
{
item->SetHilight(false);
RefreshLine(item);
}
if (item->HasChildren())
{
wxArrayGenericTreeItems& children = item->GetChildren();
size_t count = children.Count();
for ( size_t n = 0; n < count; ++n )
{
UnselectAllChildren(children[n]);
}
}
}
void wxGenericTreeCtrl::UnselectAll()
{
wxTreeItemId rootItem = GetRootItem();
// the tree might not have the root item at all
if ( rootItem )
{
UnselectAllChildren((wxGenericTreeItem*) rootItem.m_pItem);
}
}
// Recursive function !
// To stop we must have crt_item<last_item
// Algorithm :
// Tag all next children, when no more children,
// Move to parent (not to tag)
// Keep going... if we found last_item, we stop.
bool wxGenericTreeCtrl::TagNextChildren(wxGenericTreeItem *crt_item, wxGenericTreeItem *last_item, bool select)
{
wxGenericTreeItem *parent = crt_item->GetParent();
if (parent == NULL) // This is root item
return TagAllChildrenUntilLast(crt_item, last_item, select);
wxArrayGenericTreeItems& children = parent->GetChildren();
int index = children.Index(crt_item);
wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent?
size_t count = children.Count();
for (size_t n=(size_t)(index+1); n<count; ++n)
{
if (TagAllChildrenUntilLast(children[n], last_item, select)) return true;
}
return TagNextChildren(parent, last_item, select);
}
bool wxGenericTreeCtrl::TagAllChildrenUntilLast(wxGenericTreeItem *crt_item, wxGenericTreeItem *last_item, bool select)
{
crt_item->SetHilight(select);
RefreshLine(crt_item);
if (crt_item==last_item)
return true;
if (crt_item->HasChildren())
{
wxArrayGenericTreeItems& children = crt_item->GetChildren();
size_t count = children.Count();
for ( size_t n = 0; n < count; ++n )
{
if (TagAllChildrenUntilLast(children[n], last_item, select))
return true;
}
}
return false;
}
void wxGenericTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeItem *item2)
{
m_select_me = NULL;
// item2 is not necessary after item1
// choice first' and 'last' between item1 and item2
wxGenericTreeItem *first= (item1->GetY()<item2->GetY()) ? item1 : item2;
wxGenericTreeItem *last = (item1->GetY()<item2->GetY()) ? item2 : item1;
bool select = m_current->IsSelected();
if ( TagAllChildrenUntilLast(first,last,select) )
return;
TagNextChildren(first,last,select);
}
void wxGenericTreeCtrl::DoSelectItem(const wxTreeItemId& itemId,
bool unselect_others,
bool extended_select)
{
wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
m_select_me = NULL;
bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE);
wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
//wxCHECK_RET( ( (!unselect_others) && is_single),
// wxT("this is a single selection tree") );
// to keep going anyhow !!!
if (is_single)
{
if (item->IsSelected())
return; // nothing to do
unselect_others = true;
extended_select = false;
}
else if ( unselect_others && item->IsSelected() )
{
// selection change if there is more than one item currently selected
wxArrayTreeItemIds selected_items;
if ( GetSelections(selected_items) == 1 )
return;
}
wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() );
event.m_item = item;
event.m_itemOld = m_current;
event.SetEventObject( this );
// TODO : Here we don't send any selection mode yet !
if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() )
return;
wxTreeItemId parent = GetItemParent( itemId );
while (parent.IsOk())
{
if (!IsExpanded(parent))
Expand( parent );
parent = GetItemParent( parent );
}
// ctrl press
if (unselect_others)
{
if (is_single) Unselect(); // to speed up thing
else UnselectAll();
}
// shift press
if (extended_select)
{
if ( !m_current )
{
m_current = m_key_current = (wxGenericTreeItem*) GetRootItem().m_pItem;
}
// don't change the mark (m_current)
SelectItemRange(m_current, item);
}
else
{
bool select = true; // the default
// Check if we need to toggle hilight (ctrl mode)
if (!unselect_others)
select=!item->IsSelected();
m_current = m_key_current = item;
m_current->SetHilight(select);
RefreshLine( m_current );
}
// This can cause idle processing to select the root
// if no item is selected, so it must be after the
// selection is set
EnsureVisible( itemId );
event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
GetEventHandler()->ProcessEvent( event );
}
void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, bool select)
{
if ( select )
{
DoSelectItem(itemId, !HasFlag(wxTR_MULTIPLE));
}
else // deselect
{
wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
wxCHECK_RET( item, wxT("SelectItem(): invalid tree item") );
item->SetHilight(false);
RefreshLine(item);
}
}
void wxGenericTreeCtrl::FillArray(wxGenericTreeItem *item,
wxArrayTreeItemIds &array) const
{
if ( item->IsSelected() )
array.Add(wxTreeItemId(item));
if ( item->HasChildren() )
{
wxArrayGenericTreeItems& children = item->GetChildren();
size_t count = children.GetCount();
for ( size_t n = 0; n < count; ++n )
FillArray(children[n], array);
}
}
size_t wxGenericTreeCtrl::GetSelections(wxArrayTreeItemIds &array) const
{
array.Empty();
wxTreeItemId idRoot = GetRootItem();
if ( idRoot.IsOk() )
{
FillArray((wxGenericTreeItem*) idRoot.m_pItem, array);
}
//else: the tree is empty, so no selections
return array.Count();
}
void wxGenericTreeCtrl::EnsureVisible(const wxTreeItemId& item)
{
wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
if (!item.IsOk()) return;
wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
// first expand all parent branches
wxGenericTreeItem *parent = gitem->GetParent();
if ( HasFlag(wxTR_HIDE_ROOT) )
{
while ( parent && parent != m_anchor )
{
Expand(parent);
parent = parent->GetParent();
}
}
else
{
while ( parent )
{
Expand(parent);
parent = parent->GetParent();
}
}
//if (parent) CalculatePositions();
ScrollTo(item);
}
void wxGenericTreeCtrl::ScrollTo(const wxTreeItemId &item)
{
if (!item.IsOk()) return;
// We have to call this here because the label in
// question might just have been added and no screen
// update taken place.
if (m_dirty)
#if defined( __WXMSW__ ) || defined(__WXMAC__)
Update();
#else
wxYieldIfNeeded();
#endif
wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
// now scroll to the item
int item_y = gitem->GetY();
int start_x = 0;
int start_y = 0;
GetViewStart( &start_x, &start_y );
start_y *= PIXELS_PER_UNIT;
int client_h = 0;
int client_w = 0;
GetClientSize( &client_w, &client_h );
if (item_y < start_y+3)
{
// going down
int x = 0;
int y = 0;
m_anchor->GetSize( x, y, this );
y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
int x_pos = GetScrollPos( wxHORIZONTAL );
// Item should appear at top
SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, item_y/PIXELS_PER_UNIT );
}
else if (item_y+GetLineHeight(gitem) > start_y+client_h)
{
// going up
int x = 0;
int y = 0;
m_anchor->GetSize( x, y, this );
y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
item_y += PIXELS_PER_UNIT+2;
int x_pos = GetScrollPos( wxHORIZONTAL );
// Item should appear at bottom
SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, (item_y+GetLineHeight(gitem)-client_h)/PIXELS_PER_UNIT );
}
}
// FIXME: tree sorting functions are not reentrant and not MT-safe!
static wxGenericTreeCtrl *s_treeBeingSorted = NULL;
static int LINKAGEMODE tree_ctrl_compare_func(wxGenericTreeItem **item1,
wxGenericTreeItem **item2)
{
wxCHECK_MSG( s_treeBeingSorted, 0, wxT("bug in wxGenericTreeCtrl::SortChildren()") );
return s_treeBeingSorted->OnCompareItems(*item1, *item2);
}
int wxGenericTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
const wxTreeItemId& item2)
{
return wxStrcmp(GetItemText(item1), GetItemText(item2));
}
void wxGenericTreeCtrl::SortChildren(const wxTreeItemId& itemId)
{
wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
wxCHECK_RET( !s_treeBeingSorted,
wxT("wxGenericTreeCtrl::SortChildren is not reentrant") );
wxArrayGenericTreeItems& children = item->GetChildren();
if ( children.Count() > 1 )
{
m_dirty = true;
s_treeBeingSorted = this;
children.Sort(tree_ctrl_compare_func);
s_treeBeingSorted = NULL;
}
//else: don't make the tree dirty as nothing changed
}
wxImageList *wxGenericTreeCtrl::GetImageList() const
{
return m_imageListNormal;
}
wxImageList *wxGenericTreeCtrl::GetButtonsImageList() const
{
return m_imageListButtons;
}
wxImageList *wxGenericTreeCtrl::GetStateImageList() const
{
return m_imageListState;
}
void wxGenericTreeCtrl::CalculateLineHeight()
{
wxClientDC dc(this);
m_lineHeight = (int)(dc.GetCharHeight() + 4);
if ( m_imageListNormal )
{
// Calculate a m_lineHeight value from the normal Image sizes.
// May be toggle off. Then wxGenericTreeCtrl will spread when
// necessary (which might look ugly).
int n = m_imageListNormal->GetImageCount();
for (int i = 0; i < n ; i++)
{
int width = 0, height = 0;
m_imageListNormal->GetSize(i, width, height);
if (height > m_lineHeight) m_lineHeight = height;
}
}
if (m_imageListButtons)
{
// Calculate a m_lineHeight value from the Button image sizes.
// May be toggle off. Then wxGenericTreeCtrl will spread when
// necessary (which might look ugly).
int n = m_imageListButtons->GetImageCount();
for (int i = 0; i < n ; i++)
{
int width = 0, height = 0;
m_imageListButtons->GetSize(i, width, height);
if (height > m_lineHeight) m_lineHeight = height;
}
}
if (m_lineHeight < 30)
m_lineHeight += 2; // at least 2 pixels
else
m_lineHeight += m_lineHeight/10; // otherwise 10% extra spacing
}
void wxGenericTreeCtrl::SetImageList(wxImageList *imageList)
{
if (m_ownsImageListNormal) delete m_imageListNormal;
m_imageListNormal = imageList;
m_ownsImageListNormal = false;
m_dirty = true;
// Don't do any drawing if we're setting the list to NULL,
// since we may be in the process of deleting the tree control.
if (imageList)
CalculateLineHeight();
}
void wxGenericTre
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?