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

#include <z_int1.hpp>
#include <z_scrll2.hpp>
#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
#	include "i_scrll.hpp"
#endif
#define ZAF_SCROLL_BAR_INFO
#include "img_def.cpp"
#include "gbl_def.cpp"

ZafScrollBar *ZafWindow::CornerScrollBar(void) const
{
	for (ZafWindowObject *object = SupportFirst(); object; object = object->Next())
		if (object->NumberID() == ZAF_NUMID_C_SCROLL)
			return (DynamicPtrCast(object, ZafScrollBar));
	return (ZAF_NULLP(ZafScrollBar));
}

ZafScrollBar *ZafWindow::HorizontalScrollBar(void) const
{
	for (ZafWindowObject *object = SupportFirst(); object; object = object->Next())
		if (object->NumberID() == ZAF_NUMID_HZ_SCROLL)
			return (DynamicPtrCast(object, ZafScrollBar));
	return (ZAF_NULLP(ZafScrollBar));
}

ZafScrollBar *ZafWindow::VerticalScrollBar(void) const
{
	for (ZafWindowObject *object = SupportFirst(); object; object = object->Next())
		if (object->NumberID() == ZAF_NUMID_VT_SCROLL)
			return (DynamicPtrCast(object, ZafScrollBar));
	return (ZAF_NULLP(ZafScrollBar));
}

// ----- ZafScrollBar -------------------------------------------------------

ZafScrollBar::ZafScrollBar(ZafScrollBarType tScrollType) :
	ZafWindow(0, 0, 0, 0),
	scrollType((ZafScrollBarType)-1), scrollData(ZAF_NULLP(ZafScrollData)),
	autoSize(true)
{
	// Initialize the scroll information.
	SetScrollType(tScrollType);
	if (tScrollType != ZAF_HORIZONTAL_SLIDER && tScrollType != ZAF_VERTICAL_SLIDER)
		SetSupportObject(true);

	// Initialize the scroll data.
	SetScrollData(new ZafScrollData(0, 100, 0, 1, 1));

	SetDestroyable(false);
	SetMoveable(false);
	SetSizeable(false);

#if defined(ZAF_MSWINDOWS)
	systemObject = supportObject ? false : true;
#elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	lButton = mButton = rButton = selected = ZAF_NULLP(ZafScrollButton);
#endif
}

ZafScrollBar::ZafScrollBar(int left, int top, int width, int height,
	long newMinimum, long newMaximum, long newCurrent, long newDelta,
	long newShowing, ZafScrollBarType tScrollType) :
	ZafWindow(left, top, width, height),
	scrollType((ZafScrollBarType)-1), scrollData(ZAF_NULLP(ZafScrollData)),
	autoSize(true)
{
	// Initialize the scroll information.
	SetScrollType(tScrollType);
	if (tScrollType != ZAF_HORIZONTAL_SLIDER && tScrollType != ZAF_VERTICAL_SLIDER)
		SetSupportObject(true);

	// Initialize the scroll data.
	SetScrollData(new ZafScrollData(newMinimum, newMaximum, newCurrent, newDelta, newShowing));

	SetDestroyable(false);
	SetMoveable(false);
	SetSizeable(false);

#if defined(ZAF_MSWINDOWS)
	systemObject = supportObject ? false : true;
#elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	lButton = mButton = rButton = selected = ZAF_NULLP(ZafScrollButton);
#endif
}

ZafScrollBar::ZafScrollBar(int left, int top, int width, int height,
	ZafScrollData *zScrollData, ZafScrollBarType tScrollType) :
	ZafWindow(left, top, width, height),
	scrollType((ZafScrollBarType)-1), scrollData(ZAF_NULLP(ZafScrollData)),
	autoSize(true)
{
	// Initialize the scroll information.
	SetScrollType(tScrollType);
	if (tScrollType != ZAF_HORIZONTAL_SLIDER && tScrollType != ZAF_VERTICAL_SLIDER)
		SetSupportObject(true);

	// Initialize the scroll data.
	SetScrollData(zScrollData ? zScrollData : new ZafScrollData);

	SetDestroyable(false);
	SetMoveable(false);
	SetSizeable(false);

#if defined(ZAF_MSWINDOWS)
	systemObject = supportObject ? false : true;
#elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	lButton = mButton = rButton = selected = ZAF_NULLP(ZafScrollButton);
#endif
}

ZafScrollBar::ZafScrollBar(const ZafScrollBar &copy) :
	ZafWindow(copy),
	scrollType((ZafScrollBarType)-1), scrollData(ZAF_NULLP(ZafScrollData)),
	autoSize(copy.autoSize)
{
	// Initialize the scroll information.
	SetScrollType(copy.scrollType);
	if (copy.ScrollData()->Destroyable())
		SetScrollData(new ZafScrollData(*copy.ScrollData()));
	else
		SetScrollData(copy.ScrollData());

#if defined(ZAF_MSWINDOWS)
	systemObject = supportObject ? false : true;
#elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	lButton = mButton = rButton = selected = ZAF_NULLP(ZafScrollButton);
#endif
}

ZafScrollBar::~ZafScrollBar(void)
{
	// Remove the data notification.
	if (scrollData)
		scrollData->SubtractNotification(this, (ZafUpdateFunction)Update);

	// Restore the string information.
	if (scrollData->Destroyable() && scrollData->NotifyCount() == 0)
		delete scrollData;
}

ZafWindowObject *ZafScrollBar::Duplicate(void)
{
	return (new ZafScrollBar(*this));
}

bool ZafScrollBar::IsA(ZafClassID compareID) const
{
	return ((compareID == classID) ? true : ZafWindow::IsA(compareID));
}

bool ZafScrollBar::IsA(ZafClassName compareName) const
{
	return (!strcmp(compareName, className) ? true : ZafWindow::IsA(compareName));
}

const ZafPaletteStruct *ZafScrollBar::MapClassPalette(ZafPaletteType type, ZafPaletteState state)
{
	const ZafPaletteStruct *palette = MapPalette(defaultPaletteMap, type, state);
	return (palette ? palette : ZafWindow::MapClassPalette(type, state));
}

ZafWindowObject *ZafScrollBar::NotifyFocus(ZafWindowObject *focusObject, bool setFocus)
{
	// Defer to the base class.
	return (ZafWindowObject::NotifyFocus(focusObject, setFocus));
}

bool ZafScrollBar::SetAcceptDrop(bool )
{
	// acceptDrop is false for this class.
	acceptDrop = false;
	return (acceptDrop);
}

bool ZafScrollBar::SetAutoSize(bool setAutoSize)
{
	// Make sure the attribute has changed.
	if (autoSize != setAutoSize && !screenID)
		autoSize = setAutoSize;

	// Return the current attribute.
	return (autoSize);
}

bool ZafScrollBar::SetBordered(bool )
{
	// bordered is false for this class.
	bordered = false;
	return (bordered);
}

bool ZafScrollBar::SetDestroyable(bool )
{
	// destroyable is false for this class.
	destroyable = false;
	return (destroyable);
}

bool ZafScrollBar::SetLocked(bool )
{
	// locked is false for this class.
	locked = false;
	return (locked);
}

bool ZafScrollBar::SetMaximized(bool )
{
	// maximized is false for this class.
	maximized = false;
	return (maximized);
}

bool ZafScrollBar::SetMinimized(bool )
{
	// minimized is false for this class.
	minimized = false;
	return (minimized);
}

bool ZafScrollBar::SetModal(bool )
{
	// modal is false for this class.
	modal = false;
	return (modal);
}

bool ZafScrollBar::SetMoveable(bool )
{
	// moveable is false for this class.
	moveable = false;
	return (moveable);
}

bool ZafScrollBar::SetNormalHotKeys(bool )
{
	// normalHotKeys is false for this class.
	normalHotKeys = false;
	return (normalHotKeys);
}

ZafWindow *ZafScrollBar::SetOwner(ZafWindow *)
{
	// owner is null for this class.
	owner = ZAF_NULLP(ZafWindow);
	return (owner);
}

bool ZafScrollBar::SetParentPalette(bool )
{
	// parentPalette is false for this class.
	parentPalette = false;
	return (parentPalette);
}

ZafError ZafScrollBar::SetScrollData(ZafScrollData *tScrollData)
{
	// Remove the data notification.
	if (scrollData)
		scrollData->SubtractNotification(this, (ZafUpdateFunction)Update);

	// Reset the scroll data.
	if (scrollData && scrollData != tScrollData &&
		scrollData->Destroyable() && scrollData->NotifyCount() == 0)
		delete scrollData;
	scrollData = tScrollData ? tScrollData : new ZafScrollData;

	// Add the scroll notification.
	scrollData->AddNotification(this, (ZafUpdateFunction)Update);
	return (OSSetScroll());
}

ZafScrollBarType ZafScrollBar::SetScrollType(ZafScrollBarType setScrollType)
{
	// Make sure the attribute has changed.
	if (scrollType != setScrollType && !screenID)
	{
		scrollType = setScrollType;

		if (scrollType == ZAF_HORIZONTAL_SLIDER || scrollType == ZAF_VERTICAL_SLIDER)
		{
			SetRegionType(ZAF_INSIDE_REGION);
			SetNoncurrent(false);
			SetSupportObject(false);
		}
	}

	// Return the current attribute.
	return (scrollType);
}

ZafSelectionType ZafScrollBar::SetSelectionType(ZafSelectionType )
{
	// selectionType is ZAF_SINGLE_SELECTION for this class.
	selectionType = ZAF_SINGLE_SELECTION;
	return (selectionType);
}

bool ZafScrollBar::SetSizeable(bool )
{
	// sizeable is false for this class.
	sizeable = false;
	return (sizeable);
}

bool ZafScrollBar::SetSupportObject(bool setSupportObject)
{
	// Make sure the attribute has changed.
	if (!parent && supportObject != setSupportObject)
	{
		if (setSupportObject && (scrollType == ZAF_HORIZONTAL_SLIDER ||
			scrollType == ZAF_VERTICAL_SLIDER))
			return (supportObject);

		supportObject = setSupportObject;

		// Check ancillary flags.
		if (supportObject)
		{
			SetRegionType(ZAF_AVAILABLE_REGION);
			SetNoncurrent(true);

			// Set the numberID and stringID.
			if (ScrollType() == ZAF_VERTICAL_SCROLL)
			{
				SetNumberID(vNumberID);
				SetStringID(vStringID);
			}
			else if (ScrollType() == ZAF_HORIZONTAL_SCROLL)
			{
				SetNumberID(hNumberID);
				SetStringID(hStringID);
			}
			else if (ScrollType() == ZAF_CORNER_SCROLL)
			{
				SetNumberID(cNumberID);
				SetStringID(cStringID);
			}
		}
		else
		{
			SetRegionType(ZAF_INSIDE_REGION);
			SetNoncurrent(false);

			// Clear numberID and stringID.
			numberID = 0;
			ZafIChar *temp = ZAF_NULLP(ZafIChar);
			SetStringID(temp);
		}
#if defined(ZAF_MSWINDOWS)
		systemObject = supportObject ? false : true;
#endif
	}

	// Return the current attribute.
	return (supportObject);
}

bool ZafScrollBar::SetTemporary(bool )
{
	// temporary is false for this class.
	temporary = false;
	return (temporary);
}

ZafError ZafScrollBar::Update(ZafScrollBar *scrollBar, ZafUpdateType type)
{
	ZafError retVal = ZAF_ERROR_INVALID;
	if (type & ZAF_UPDATE_OBJECT)
		retVal = scrollBar->OSSetScroll();
	if (type & ZAF_UPDATE_DATA)
		retVal = scrollBar->OSGetScroll();
	return (retVal);
}

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafScrollBar::ZafScrollBar(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafWindow(name, persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY)),
	scrollType((ZafScrollBarType)-1), scrollData(ZAF_NULLP(ZafScrollData))
{
	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafScrollBar::ReadData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());

#if defined(ZAF_MSWINDOWS)
	systemObject = supportObject ? false : true;
#elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	lButton = mButton = rButton = selected = ZAF_NULLP(ZafScrollButton);
#endif
}

ZafElement *ZafScrollBar::Read(const ZafIChar *name, ZafObjectPersistence &persist)
{
	return (new ZafScrollBar(name, persist));
}

void ZafScrollBar::ReadData(ZafObjectPersistence &persist)
{
	// Read the data.
	ZafUInt16 flag1, flag2;
	ZafIChar scrollName[ZAF_MAXNAMELEN];
	ZafFile *file = persist.CurrentFile();
	*file >> flag1 >> flag2 >> scrollName;
	// flag1
	autoSize = (flag1 & 0x0001) ? true : false;
	// flag2
	SetScrollType((ZafScrollBarType)(flag2 & 0x000F));

	SetScrollData(scrollName[0] ? new ZafScrollData(scrollName, persist) : new ZafScrollData);
}

void ZafScrollBar::Write(ZafObjectPersistence &persist)
{
	// Bypass ZafWindow calls to keep the children from being saved.
	ZafWindowObject::Write(persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafWindow::WriteData(persist);
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafScrollBar::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafScrollBar::WriteData(ZafObjectPersistence &persist)
{
	// Write the scroll data.
	ZafUInt16 flag1 = 0, flag2 = 0;
	const ZafIChar *scrollName = scrollData ? scrollData->StringID() : ZAF_NULLP(ZafIChar);
	ZafFile *file = persist.CurrentFile();
	// flag1
	flag1 |= (ZafUInt16)(autoSize ? 0x0001 : 0);
	// flag2
	flag2 |= (ZafUInt16)(scrollType & 0x000F);
	*file << flag1 << flag2 << scrollName;

	if (scrollData)
		scrollData->Write(persist);
}
#endif
