//	Zinc Application Framework - I_TREE.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <time.h>
#include <z_error.hpp>
#include <z_keymap.hpp>
#include <z_scrll2.hpp>
#include <z_tree.hpp>
#include <z_utils.hpp>

// ----- ZafTreeList --------------------------------------------------------

ZafWindowObject *ZafTreeList::Add(ZafWindowObject *object, ZafWindowObject *position)
{
	ZafWindow::Add(object, position);

	ZafTreeItem *item = DynamicPtrCast(object, ZafTreeItem);
	if (item)
	{
		if (!current)
		{
			current = object;
			if (SelectionType() == ZAF_SINGLE_SELECTION)
				object->SetSelected(true);
		}

		if (screenID)
		{
			int showing = 1;
			int itemHeight = display->cellHeight - display->preSpace - display->postSpace;
			int showable = clientRegion.Height() / itemHeight;
			ZafTreeItem *item = ViewLast();
			while (item && showing < showable)
			{
				ZafTreeItem *prevItem = item->ViewPrevious();
				if (item == firstVisible && prevItem)
					firstVisible = prevItem;
				item = prevItem;
				showing++;
			}

			ResizeVisibleItems(firstVisible);
			Event(S_VSCROLL_COMPUTE);
			Redisplay();
		}
	}

	return (object);
}

ZafRegionStruct ZafTreeList::ConvertToDrawRegion(const ZafWindowObject *object,
	const ZafRegionStruct *zafRegion) const
{
	return (ZafWindowObject::ConvertToDrawRegion(object, zafRegion));
}

ZafPositionStruct ZafTreeList::ConvertToOSPosition(const ZafWindowObject *object,
	const ZafPositionStruct *zafPosition) const
{
	ZafPositionStruct osPosition = ZafWindow::ConvertToOSPosition(object, zafPosition);
	if (object != this && !object->SupportObject())
	{
		ZafScrollBar *hzScrollBar = HorizontalScrollBar();
		if (hzScrollBar)
			osPosition.column -= (int)hzScrollBar->ScrollData()->Current();
	}
	return (osPosition);
}

ZafPositionStruct ZafTreeList::ConvertToZafPosition(const ZafWindowObject *object,
	const ZafPositionStruct *osPosition) const
{
	ZafPositionStruct zafPosition = ZafWindow::ConvertToZafPosition(object, osPosition);
	if (object != this && !object->SupportObject())
	{
		ZafScrollBar *hzScrollBar = HorizontalScrollBar();
		if (hzScrollBar)
			zafPosition.column += (int)hzScrollBar->ScrollData()->Current();
	}
	return (zafPosition);
}

ZafEventType ZafTreeList::DispatchMouseEvent(const ZafEventStruct &event)
{
	return (ZafWindowObject::DispatchMouseEvent(event));
}

ZafWindowObject *ZafTreeList::FindMouseObject(const ZafEventStruct &event)
{
	ZafPositionStruct position;
	position.line = event.osEvent.position.line;
	position.column = event.osEvent.position.column;
#if defined(ZAF_GRAPHICS_MODE)
	position.coordinateType = ZAF_PIXEL;
#else
	position.coordinateType = ZAF_CELL;
#endif
	// Convert mouse position to the coordinates of this object.
	ZafPositionStruct mousePosition = ConvertToZafPosition(this, &position);

	ZafRegionStruct windowClient = ClientRegion();
	if (!windowClient.Overlap(mousePosition))
	{
		return ZafWindow::FindMouseObject(event);
	}

	ZafTreeItem *object;
	for (object = FirstVisible(); object;)
	{
		if (object->Visible() && object->zafRegion.Overlap(mousePosition))
			break;

		object = (object == LastVisible()) ? 0 : object->ViewNext();
	}

	return (object ? object : ZafWindowObject::FindMouseObject(event));
}

ZafEventType ZafTreeList::DragDropEvent(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;

	switch (ccode)
	{
	case S_BEGIN_DRAG:
		windowManager->CaptureMouse(this);
		windowManager->dragObject = Current();
		break;

	case S_DROP_DEFAULT:
		if (windowManager->dragObject->MoveDraggable())
			ccode = S_DROP_MOVE;
		else if (windowManager->dragObject->CopyDraggable())
			ccode = S_DROP_COPY;
		else
		{
			ccode = S_ERROR;
			break;
		}
		//Continue.
	case S_DROP_COPY:
	case S_DROP_MOVE:
		if (Disabled() || !AcceptDrop() || windowManager->dragObject == this)
			return (S_ERROR);
		else if (windowManager->dragObject->IsA(ID_ZAF_TREE_ITEM))
		{
			// Try to find an overlapping item.
			ZafWindow *dropObject = ZAF_NULLP(ZafWindow);
			for (ZafTreeItem *item = firstVisible; item; item = item->ViewNext())
				if (item->zafRegion.Overlap(event.position))
				{
					dropObject = item;
					break;
				}
			if (!dropObject)
				dropObject = this;

			// Make sure drop is allowed.
			ZafWindowObject *dropTest = dropObject;
			while (dropTest)
			{
				if (dropTest == windowManager->dragObject)
				{
					// Can't drop item into its own sub-item.
					return S_ERROR;
				}
				dropTest = dropTest->parent;
			}

			ZafWindowObject *dragObject;
			if (ccode == S_DROP_MOVE)
			{
				dragObject = windowManager->dragObject;
				ZafWindow *dragParent = DynamicPtrCast(dragObject->parent, ZafWindow);
				dragParent->Subtract(dragObject);
			}
			else
				dragObject = windowManager->dragObject->Duplicate();
			dropObject->Add(dragObject);
		}
		break;

	default:
		ccode = ZafWindowObject::DragDropEvent(event);
		break;
	}

	return (ccode);
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafTreeList::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	// Begin the drawing operation.
	ZafPaletteState state = PaletteState();
	ZafRegionStruct drawRegion = BeginDraw();

	display->SetClipRegion(event.region);

	// Redraw the list background.
	display->SetPalette(LogicalPalette(ZAF_PM_BACKGROUND, state));
	display->Rectangle(drawRegion, 0, true);

	// Return the control code.
	EndDraw();

	// Draw the list items that appear on the screen.
	for (ZafTreeItem *object = firstVisible; object; object = object->ViewNext())
	{
		if (object->zafRegion.Overlap(event.region) &&
			object->AutomaticUpdate() && object->Visible())
			object->Draw(event, ccode);

		if (object == lastVisible)
			break;
	}

	return (ccode);
}

ZafEventType ZafTreeList::DrawFocus(ZafRegionStruct &region, ZafEventType ccode)
{
	return (ZafWindow::DrawFocus(region, ccode));
}
#endif

ZafEventType ZafTreeList::Event(const ZafEventStruct &event)
{
	if (modifyMode && event.InputType() == E_MOUSE)
		return (Modify(event));

	ZafEventType ccode;
	if (event.InputType() == E_KEY || event.InputType() == E_MOUSE)
		ccode = LogicalEvent(event);
	else if (event.type == E_OSEVENT)
		return (ZafTreeList::OSEvent(event));
	else
		ccode = event.type;

	if (modifyMode && event.InputType() == E_MOUSE)
		return (Modify(event));

	ZafTreeItem *object;

	switch (ccode)
	{
	// ----- Create messages -----
	case S_INITIALIZE:
		ccode = ZafWindow::Event(event);
		firstVisible = ViewFirst();
		break;

	case S_CURRENT:
	case N_CURRENT:
		ccode = ZafWindowObject::Event(event);
		if (current)
			Current()->Event(event);
		break;

	case S_NON_CURRENT:
	case N_NON_CURRENT:
		if (current)
			Current()->Event(event);
		ccode = ZafWindowObject::Event(event);
		break;

	// ----- Position & Size messages -----
	case N_SIZE:
		ResizeVisibleItems(firstVisible);
		Redisplay();
		Event(S_HSCROLL_COMPUTE);
		Event(S_VSCROLL_COMPUTE);
		break;

	// ----- Selection messages -----
	case L_SELECT:
	case L_DOUBLE_CLICK:
		object = ViewCurrent();
		if (object)
		{
			if (object->Expandable() && ccode == L_SELECT)
				object->Event(event);
//				object->ToggleExpanded();
			else
				(object->*(object->memberUserFunction))(event, ccode);
		}
		break;

	case L_BEGIN_SELECT:
	case L_END_SELECT:
//	case L_END_COPY_DRAG:
	case L_CONTINUE_SELECT:
//	case L_CONTINUE_COPY_DRAG:
		{
			// Continue select should not be processed if we don't have focus
			// and we're not being dragging onto.
			if (ccode == L_CONTINUE_SELECT && !Focus() && !windowManager->dragObject)
				break;

			if (Draggable() && !windowManager->dragObject)
				ZafWindowObject::Event(event);

			if (windowManager->dragObject)
			{
//				if (ccode == L_CONTINUE_SELECT)// || ccode == L_CONTINUE_COPY_DRAG)
					ZafWindowObject::Event(event);
/* START BLOCK COMMENT
**					else if (ccode == L_END_SELECT)// || ccode == L_END_COPY_DRAG)
**					{
**						if (object)
**							object->Event(event);
**						else
**							ZafWindowObject::Event(event);
**					}
END BLOCK COMMENT */
				break;
			}

			// Check for out-of-bounds.
			ZafPositionStruct mousePosition = event.position;
			ZafRegionStruct windowClient = clientRegion;
			// event.position is 0,0 based for the visible client region after 
			// it has been dispatched.
			windowClient.HzShift(-windowClient.left);
			windowClient.VtShift(-windowClient.top);

			if (!windowClient.Overlap(event.position))
			{
				// Check if over a scroll bar, since this is an atom.
				for (ZafWindowObject *supportObject = SupportFirst();
					supportObject; supportObject = supportObject->Next())
				{
					if (supportObject->zafRegion.Overlap(event.position))
						return (supportObject->DispatchMouseEvent(event));
				}
				return (ccode);
			}

			// Try to find an overlapping item.
			for (object = firstVisible; object; object = object->ViewNext())
				if (object->zafRegion.Overlap(event.position))
				{
					object->SetFocus(true);
					SetViewCurrent(object);
					if ((ccode == L_CONTINUE_SELECT || ccode == L_BEGIN_SELECT) &&
						!object->Selected())
						object->SetSelected(true);
					else if (SelectionType() != ZAF_SINGLE_SELECTION && ccode == L_BEGIN_SELECT)
						object->ToggleSelected();
					break;
				}

			if (!object)
			{
				// The tree list gets focus if no child did.
				if (ccode == L_BEGIN_SELECT && !Disabled() && !Noncurrent())
					SetFocus(true);

				break;
			}

			// Check for a new selection.
			if (ccode == L_END_SELECT)
			{
				ZafEventStruct uEvent = event;
				uEvent.type = L_SELECT;

				mousePosition.line -= object->zafRegion.top;
				mousePosition.column -= object->zafRegion.left;

				ZafScrollBar *hzScrollBar = HorizontalScrollBar();
				if (hzScrollBar)
					mousePosition.column += (int)hzScrollBar->ScrollData()->Current();

				// If up-click was on expand button, expand the item.
				if (object->expandRegion.Overlap(mousePosition))
					object->ToggleExpanded();
				else // Otherwise call the user callback.
					(object->*memberUserFunction)(uEvent, L_SELECT);
			}
		}
		break;

	// ----- Movement messages -----
	case L_DOWN:
	case L_FIRST:
	case L_LAST:
	case L_PGDN:
	case L_PGUP:
	case L_UP:
		ccode = MoveEvent(ccode);
		break;

	case L_NEXT:
	case L_PREVIOUS:
		ccode = S_UNKNOWN;
		break;

	default:
		if (event.InputType() != E_MOUSE)
			ccode = ZafWindow::Event(event);
		break;
	}

	// Return the control code.
	return (ccode);
}

void ZafTreeList::GetClip(ZafWindowObject *object, ZafRegionStruct &clip,
	ZafRegionStruct &viewPort)
{
	ZafWindow::GetClip(object, clip, viewPort);
	if (object != this && !object->SupportObject())
	{
		ZafScrollBar *hzScrollBar = HorizontalScrollBar();
		if (hzScrollBar)
		{
			int hzShift = -(int)hzScrollBar->ScrollData()->Current();
			viewPort.HzShift(hzShift);
		}
	}
}

bool ZafTreeList::ItemInView(ZafTreeItem *item)
{
	bool inView = false;
	for (ZafTreeItem *testItem = firstVisible; testItem; testItem = testItem->ViewNext())
	{
		if (testItem == item)
			return (true);
		if (testItem == lastVisible)
			break;
	}

	return inView;
}

ZafEventType ZafTreeList::MoveEvent(const ZafEventStruct &event)
{
	// Determine the new selection.
	ZafEventType ccode;
	if (event.InputType() == E_KEY || event.InputType() == E_MOUSE)
		ccode = LogicalEvent(event);
	else
		ccode = event.type;

	ZafTreeItem *object = ViewCurrent();
	if (!object)
		return (S_ERROR);
	ZafTreeItem *cObject = object;

	// Determine the previous non-disabled item in the list.
	ZafTreeItem *pObject = cObject ? cObject->ViewPrevious() : ZAF_NULLP(ZafTreeItem);
	while (pObject && pObject->Disabled())
		pObject = pObject->ViewPrevious();

	// Determine the next non-disabled item in the list.
	ZafTreeItem *nObject = cObject ? cObject->ViewNext() : ZAF_NULLP(ZafTreeItem);
	while (nObject && nObject->Disabled())
		nObject = nObject->ViewNext();

	switch (ccode)
	{
	case L_UP:
	case L_EXTEND_PREVIOUS:
		if (pObject)
			object = pObject;
		break;

	case L_DOWN:
	case L_EXTEND_NEXT:
		if (nObject)
			object = nObject;
		break;

	case L_PGUP:
		// Check for page actions.
		if (!object || !pObject)
			break; // No current object exists.
		else if (object == firstVisible || firstVisible->Disabled())
		{
			int count = clientRegion.Height() / object->zafRegion.Height() - 1;
			while (count-- > 0 && object->ViewPrevious())
				object = object->ViewPrevious();
		}
		else 
			object = firstVisible;

		while (object && object->Disabled())
			object = object->ViewNext();
		break;

	case L_PGDN:
		// Check for page actions.
		if (!object || !nObject)
			break; // No current object exists.
		else if (object == lastVisible->ViewPrevious() || lastVisible->Disabled())
		{
			int count = clientRegion.Height() / object->zafRegion.Height() - 1;
			while (count-- > 0 && object->ViewNext())
				object = object->ViewNext();
		}
		else
			object = lastVisible;

		while (object && object->Disabled())
			object = object->ViewPrevious();
		break;

	case L_FIRST:
		{
		object = ViewFirst();
		while (object && object->Disabled())
			object = object->ViewNext();
		}
		break;

	case L_LAST:
		{
		object = ViewLast();
		while (object && object->Disabled())
			object = object->ViewPrevious();
		}
		break;
	}

	// Check the current object.
	if (object && object != current)
	{
		if (SelectionType() == ZAF_SINGLE_SELECTION)
			object->SetSelected(true);

		// Reset the current object.
		object->SetFocus(true);

		// Check the scroll information.
		ScrollEvent(S_VSCROLL_CHECK);
	}
	return (ccode);
}

ZafWindowObject *ZafTreeList::NotifyFocus(ZafWindowObject *focusObject, bool setFocus)
{
	return (ZafWindowObject::NotifyFocus(focusObject, setFocus));
}

ZafWindowObject *ZafTreeList::NotifySelection(ZafWindowObject *tSelectedObject, bool setSelected)
{
	// Check for a valid object.
	ZafTreeItem *selectedObject = DynamicPtrCast(tSelectedObject, ZafTreeItem);
	if (!selectedObject)
		return (ZAF_NULLP(ZafWindowObject));

	// Update the old selected objects. If a window allows multiple 
	// selections, selecting an object doesn't affect other objects 
	// in the window.
	if (SelectionType() == ZAF_SINGLE_SELECTION && !selectedObject->SupportObject())
	{
		if (setSelected)
		{
			// Un-select all objects except "selectedObject."
			for (ZafTreeItem *object = ViewFirst(); object; object = object->ViewNext())
				if (object->Selected() && object != selectedObject)
					object->SetSelected(false);
		}
		else
		{
			// Check for a valid change of selection.
			ZafTreeItem *object = ViewFirst();
			while (object)
				if (object->Selected() && object != selectedObject)
					break;
				else
					object = object->ViewNext();

			// De-selection is not allowed.
			if (!object)
				selectedObject->selected = true;
		}
	}

	// Return the object selection.
	return (selectedObject);
}

void ZafTreeList::ResizeVisibleItems(ZafTreeItem *startItem)
{
	if (!firstVisible)
	{
		if (ViewFirst())
			firstVisible = ViewFirst();
		else
			return;
	}

	if (!startItem)
		startItem = firstVisible;

	int height = display->cellHeight - display->preSpace - display->postSpace;
	int line = 0;
	if (startItem != firstVisible && startItem->ViewPrevious())
		line = startItem->ViewPrevious()->zafRegion.bottom + 1;
	lastVisible = ViewLast();

	for (ZafTreeItem *item = startItem; item; item = item->ViewNext())
	{
		item->Event(S_COMPUTE_SIZE);
		if (!OSDraw())
			height = item->zafRegion.bottom - item->zafRegion.top;
		ZafRegionStruct newRegion;
		newRegion.left = 0;
		newRegion.right = item->zafRegion.Width();
		newRegion.top = line;
		newRegion.bottom = line + height - 1;
		newRegion.coordinateType = item->zafRegion.coordinateType;
		line = newRegion.bottom + 1;

		// Mofify the item's region.
		item->SetRegion(newRegion);
		item->OSSize();

		// Check for lastVisible and manage the scroll values.
		if (item->zafRegion.bottom >= clientRegion.bottom)
		{
			lastVisible = item;
			break;
		}
	}
}

ZafEventType ZafTreeList::ScrollEvent(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case S_VSCROLL_CHECK:
		{
		ZafTreeItem *currentItem = ViewCurrent();
		if (!currentItem)
			break;

		// Dont include partially visible items.
		ZafTreeItem *lastItem = lastVisible;
		if (lastItem->zafRegion.bottom > clientRegion.bottom)
			lastItem = lastItem->ViewPrevious();

		bool currentItemInView = true;
		ZafTreeItem *item;
		for (item = firstVisible; item; item = item->ViewNext())
		{
			if (item == currentItem)
				break;
			else if (item == lastItem)
			{
				currentItemInView = false;
				break;
			}
		}

		if (!currentItemInView)
		{
			ZafScrollStruct vScroll;
			vScroll.delta = 0;

			while (item && item != currentItem)
			{
				vScroll.delta++;
				item = item->ViewNext();
			}

			if (!item)
			{
				vScroll.delta = 0;
				item = firstVisible;
				while (item && item != currentItem)
				{
					vScroll.delta--;
					item = item->ViewPrevious();
				}
			}

			Event(ZafEventStruct(S_VSCROLL, 0, vScroll));
		}
		}
		break;

	case S_VSCROLL:
	case N_VSCROLL:
		{
		if (event.scroll.delta > 0)
		{
			for (int i = (int)event.scroll.delta; i > 0 && firstVisible; i--)
				firstVisible = firstVisible->ViewNext();
		}
		else if (event.scroll.delta < 0)
		{
			for (int i = (int)event.scroll.delta; i < 0 && firstVisible; i++)
				firstVisible = firstVisible->ViewPrevious();
		}
		else
			return (S_ERROR);

		automaticUpdate = false;
		ResizeVisibleItems(firstVisible);
		automaticUpdate = true;

		// Update only the client region.
		OSInvalidateRegion(&clientRegion);

		// Adjust the scroll values, if appropriate.
		if (ccode == S_VSCROLL)
		{
			ZafScrollBar *scrollBar = VerticalScrollBar();
			if (scrollBar)
				scrollBar->Event(event);
		}
		}
		break;

	case S_HSCROLL:
	case N_HSCROLL:
		{
			if (event.scroll.delta == 0)
				return (S_ERROR);

			// Adjust the scroll values, if appropriate.
			if (ccode == S_HSCROLL)
			{
				ZafScrollBar *scrollBar = HorizontalScrollBar();
				if (scrollBar)
					scrollBar->Event(event);
			}

			// Update only the client region.
			Redisplay();
		}
		break;

	case S_HSCROLL_COMPUTE:
		{
		// Check for a scroll-bar.
		ZafScrollBar *scrollBar = HorizontalScrollBar();
		if (!scrollBar)
			return (S_ERROR);

		// Reset the scroll values.
		ZafScrollStruct hScroll;
		hScroll.current = scrollBar->ScrollData()->Current();
		hScroll.delta = display->cellWidth;
		hScroll.minimum = 0;
		hScroll.showing = clientRegion.Width();
		hScroll.maximum = 0;
		for (ZafTreeItem *object = ViewFirst(); object; object = object->ViewNext())
			if (object->textRegion.right > hScroll.maximum)
				hScroll.maximum = object->textRegion.right;
		hScroll.maximum -= hScroll.showing;
		if (hScroll.maximum < 0)
			hScroll.maximum = 0;
		if (hScroll.current > hScroll.maximum)
		{
			hScroll.current = hScroll.maximum;
			if (screenID)
				Redisplay();
		}

		// Adjust the vertical scroll-bar values.
		scrollBar->ScrollData()->SetScroll(hScroll);
		}
		break;

	case S_VSCROLL_COMPUTE:
		{
		// Check for a scroll-bar.
		ZafScrollBar *scrollBar = VerticalScrollBar();
		if (!scrollBar)
			return (S_ERROR);

		// Reset the scroll values.
		ZafScrollStruct vScroll;
		vScroll.delta = 1;
		vScroll.minimum = vScroll.maximum = 0;
		vScroll.showing = vScroll.current = 0;

		int count = 0;
		bool inView = false;
		for (ZafTreeItem *item = ViewFirst(); item; item = item->ViewNext())
		{
			if (item == firstVisible)
			{
				inView = true;
				vScroll.current = count;
			}
			if (inView)
				vScroll.showing++;
			if (item == lastVisible)
				inView = false;
			count++;
		}

		if (lastVisible && lastVisible->zafRegion.bottom > clientRegion.bottom)
			vScroll.showing--;

		vScroll.maximum = count - vScroll.showing;
		scrollBar->Event(ZafEventStruct(S_VSCROLL_SET, 0, vScroll));
		}
		break;

	default:
		// No other messages apply to the vertical list object.
		return (S_ERROR);
	}

	// Return the control code.
	return (ccode);
}

void ZafTreeList::Sort(void)
{
	// Sort on the ZAF level.
	ZafList::Sort();
	for (ZafTreeItem *item = (ZafTreeItem *)first; item; item = (ZafTreeItem *)item->Next())
		item->Sort();

	// Items must be re-positioned in the list.
	if (screenID)
	{
		firstVisible = lastVisible = ZAF_NULLP(ZafTreeItem);
		ResizeVisibleItems(firstVisible);
		Event(S_VSCROLL_COMPUTE);
		Event(S_VSCROLL_CHECK);
		Redisplay();
	}
}

ZafWindowObject *ZafTreeList::Subtract(ZafWindowObject *object)
{
	ZafTreeItem *item = DynamicPtrCast(object, ZafTreeItem);
	if (item)
	{
		bool inView = ItemInView(item);

		ZafTreeItem *replaceItem = item->Next() ? (ZafTreeItem *)item->Next() : item->ViewPrevious();
		ZafWindowObject *currentTest = Current();

		// Test if the current object is a child of the object being removed.
		while (currentTest && currentTest != item)
			currentTest = currentTest->parent;
		if (currentTest)
			current = replaceItem;

		// Check to see if the first visible item is a child of the object
		// being removed.
		currentTest = firstVisible;
		while (currentTest && currentTest != item)
			currentTest = currentTest->parent;
		if (currentTest)
			firstVisible = replaceItem;

		if (SelectionType() == ZAF_SINGLE_SELECTION && replaceItem && replaceItem == current)
			replaceItem->SetSelected(true);
		ZafWindow::Subtract(object);

		if (screenID)
		{
			ResizeVisibleItems(inView ? replaceItem : firstVisible);
			Event(S_VSCROLL_COMPUTE);
			Event(ZafEventStruct(S_REDISPLAY));
		}
	}
	else
		ZafWindow::Subtract(object);

	return (object);
}

// ----- Attributes ---------------------------------------------------------

ZafTreeItem *ZafTreeList::ViewCurrent(void)
{
	// Return the current view item.
	return ((ZafTreeItem *)current);
}

bool ZafTreeList::SetAutomaticUpdate(bool setAutomaticUpdate)
{
	// Defer to the base class.
	return (ZafWindow::SetAutomaticUpdate(setAutomaticUpdate));
}

ZafTreeItem *ZafTreeList::SetViewCurrent(ZafTreeItem *newViewCurrent)
{
//	newViewCurrent->SetFocus(true);
	SetCurrent(newViewCurrent);
	return ViewCurrent();
}

// ----- OS Specific Functions ----------------------------------------------

void ZafTreeList::OSDestroy(void)
{
	ZafWindow::OSDestroy();

	firstVisible = lastVisible = ZAF_NULLP(ZafTreeItem);

	// Destroy the list elements (low level).
	ZafList::Destroy();

	Event(S_VSCROLL_COMPUTE);
	Redisplay();
}

ZafEventType ZafTreeList::OSEvent(const ZafEventStruct &event)
{
	return (ZafWindowObject::Event(event));
}

void ZafTreeList::ModifyOSShift(ZafPositionStruct &)
{
	// Do nothing.
}

void ZafTreeList::OSDrawChildren(ZafRegionList *)
{
	// Do nothing.
}

void ZafTreeList::OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state)
{
	ZafWindowObject::OSMapPalette(palette, type, state);
}

OSWindowID ZafTreeList::OSScreenID(ZafScreenIDType type) const
{
	return (ZafWindow::OSScreenID(type));
}

void ZafTreeList::OSRegisterObject(void)
{
	ZafWindow::OSRegisterObject();
}
