INT32 GenericTreeModel::GetPreviousLeafIndex(INT32 index) { if (GetSubtreeSize(index) == 0) { // this is a leaf itself. Go up while (GetPreviousIndex(index) == -1 && index != -1) index = GetParentIndex(index); if (index == -1) return -1; index = GetPreviousIndex(index); } // Go down to the leaf return index + GetSubtreeSize(index); }
T RangeTree<T>::GetValueOnInterval(int idx, int subtree_left, int subtree_right, int searching_left, int searching_right) const { // printf("GVOI: %d v: %d sl: %d sr: %d sel: %d ser: %d\n", idx, // tree_[idx], subtree_left, subtree_right, searching_left, // searching_right); if (subtree_left == searching_left && subtree_right == searching_right) return tree_[idx]; const int left_child_boundary = subtree_left - 1 + GetSubtreeSize(subtree_left, subtree_right) / 2; T left_result; if (IsPointInLeftChild(searching_left, subtree_left, subtree_right)) { left_result = GetValueOnInterval(GetLeftChild(idx), subtree_left, left_child_boundary, searching_left, std::min(searching_right, left_child_boundary)); } const int right_child_boundary = left_child_boundary + 1; T right_result; if (IsPointInRightChild(searching_right, subtree_left, subtree_right)) { right_result = GetValueOnInterval(GetRightChild(idx), right_child_boundary, subtree_right, std::max(searching_left, right_child_boundary), searching_right); } if (IsPointInLeftChild(searching_right, subtree_left, subtree_right)) return left_result; if (IsPointInRightChild(searching_left, subtree_left, subtree_right)) return right_result; return (*operation_)(left_result, right_result); }
void GenericTreeModel::Remove(INT32 index, BOOL all_children, BOOL delete_item) { INT32 subtreesize = all_children ? GetSubtreeSize(index) : 0; BOOL broadcast = SetChangeType(TREE_CHANGED); GenericTreeModelItem* parent = GetGenericParentItem(index); if (broadcast) { BroadcastSubtreeRemoving(parent ? parent->GetIndex() : -1, index, subtreesize); } if (!all_children) { INT32 child = GetChildIndex(index); while (child != -1) { INT32 sibling = GetSiblingIndex(child); GetGenericItemByIndex(child)->SetGenericParentItem(parent); child = sibling; } } INT32 count = subtreesize + 1; Removing(index, count); UpdateSubtreeSizes(parent, -count); OpTreeModelItem* data; for(UINT32 i = index, count_item = index + count; i < count_item; i++) m_id_to_item.Remove(m_items.Get(i)->GetID(), &data); if (delete_item) { m_items.Delete(index, count); } else { m_items.Remove(index, count); } if (broadcast) { BroadcastSubtreeRemoved(parent ? parent->GetIndex() : -1, index, subtreesize); } }
INT32 GenericTreeModel::GetNextLeafIndex(INT32 index) { if (GetSubtreeSize(index) == 0) { // this is a leaf itself. Go up while (GetSiblingIndex(index) == -1 && index != -1) index = GetParentIndex(index); if (index == -1) return -1; index = GetSiblingIndex(index); } // Go down to the leaf while (GetChildIndex(index) != -1) index = GetChildIndex(index); return index; }
void GenericTreeModel::Move(INT32 index, INT32 parent_index, INT32 previous_index) { if (index == -1 || index == previous_index) { return; } INT32 subtree_size = GetSubtreeSize(index); INT32 count = subtree_size + 1; GenericTreeModelItem* item = GetGenericItemByIndex(index); GenericTreeModelItem* parent = item->GetGenericParentItem(); GenericTreeModelItem* new_parent = GetGenericItemByIndex(parent_index); GenericTreeModelItem* new_previous = GetGenericItemByIndex(previous_index); OP_ASSERT(!new_parent || !new_previous || new_parent == new_previous->GetGenericParentItem()); if(new_previous && !new_parent) new_parent = new_previous->GetGenericParentItem(); BOOL broadcast = SetChangeType(TREE_CHANGED); // 1. Save item and subtree OpAutoArray<GenericTreeModelItem*> to_be_moved (OP_NEWA(GenericTreeModelItem*, count)); if (!to_be_moved.get()) return; for(INT32 j = 0; j < count; j++) { to_be_moved[j] = m_items.Get(index + j); } // 2. Remove the subtree if (broadcast) BroadcastSubtreeRemoving(parent ? parent->GetIndex() : -1, index, subtree_size); if(parent) UpdateSubtreeSizes(parent, -count); m_items.Remove(index,count); if (broadcast) BroadcastSubtreeRemoved(parent ? parent->GetIndex() : -1, index, subtree_size); // 3. Insert it in proper position,update parent of item if needed // NOTICE: index of new_previous and new_parent may have changed! dont use previous_index and parent_index here INT32 insert_pos = new_previous ? new_previous->GetIndex() + new_previous->GetSubtreeSize() + 1 : new_parent ? new_parent->GetIndex() + 1 : 0; for(INT32 i=0; i<count; i++) { m_items.Insert(insert_pos + i, to_be_moved[i]); } item->SetGenericParentItem(new_parent); if(new_parent) UpdateSubtreeSizes(new_parent, count); if(broadcast) { for(INT32 i=0; i<count; i++) BroadcastItemAdded(insert_pos + i); } }
INT32 GenericTreeModel::ResortItem(INT32 index) { OP_ASSERT(m_sort_listener); if (!m_sort_listener) return -1; INT32 sibling = -1; // Binary search until correct sibling is found INT32 tree_size = GetSubtreeSize(index) + 1; INT32 parent = GetParentIndex(index); INT32 parent_tree_size = GetSubtreeSize(parent); INT32 lowest = 0; INT32 highest = parent_tree_size - tree_size; GenericTreeModelItem* item = GetGenericItemByIndex(index); while (lowest < highest) { INT32 current_position = (lowest + highest) / 2; INT32 pos_to_compare_to = parent + current_position + 1; if (pos_to_compare_to >= index) pos_to_compare_to += tree_size; // convert any grandchildren up to same level we're inserting at INT32 parent_of_pos_to_compare_to = GetParentIndex(pos_to_compare_to); while (parent_of_pos_to_compare_to != parent) { pos_to_compare_to = parent_of_pos_to_compare_to; parent_of_pos_to_compare_to = GetParentIndex(pos_to_compare_to); } INT32 comparison = m_sort_listener->OnCompareItems(this, item, GetGenericItemByIndex(pos_to_compare_to)); if (comparison > 0) { lowest = current_position + 1; } else { sibling = pos_to_compare_to; highest = current_position; } } INT32 newpos = (sibling != -1 ? sibling : parent + 1 + parent_tree_size); if (newpos == index) return newpos; ModelLock lock(this); SetChangeType(TREE_CHANGED); GenericTreeModelItem** items = OP_NEWA(GenericTreeModelItem*, tree_size); if (!items) return -1; for (INT32 i = 0; i < tree_size; i++) items[i] = m_items.Get(index + i); m_items.Remove(index, tree_size); if (newpos > index) newpos -= tree_size; for (INT32 i = tree_size - 1; i >= 0; i--) m_items.Insert(newpos, items[i]); OP_DELETEA(items); return newpos; }
static bool IsPointInRightChild(int point, int left, int right) { return (left + GetSubtreeSize(left, right) / 2) <= point; }
static bool IsPointInLeftChild(int point, int left, int right) { return point < (left + GetSubtreeSize(left, right) / 2); }