/**********************************************************************
 
	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomoki SEKIYAMA <sekiyama@yahoo.co.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


// ===========================================================================
//	CDataBrowser.cp                                2004.3.16   Tomoki Sekiyama
// ===========================================================================

#ifdef PowerPlant_PCH
	#include PowerPlant_PCH
#endif

#include "CDataBrowser.h"
#include <LStream.h>
#include <LView.h>
#include <LControlImp.h>

PP_Begin_Namespace_PowerPlant


// ---------------------------------------------------------------------------
//	¥ CDataBrowser							Stream Constructor		  [public]
// ---------------------------------------------------------------------------

CDataBrowser::CDataBrowser(
	LStream*	inStream,
	ClassIDT	inImpID)

	: LControlPane(inStream, inImpID),
	  mDrawFocusRing(false)
{
	InitDataBrowser(false, false, 0, false);
}


// ---------------------------------------------------------------------------
//	¥ CDataBrowser							Parameterized Constructor [public]
// ---------------------------------------------------------------------------

CDataBrowser::CDataBrowser(
	const SPaneInfo&	inPaneInfo,
	LCommander*			inSuper,
	bool				hasHorizonalScrollBar,
	bool				hasVerticalScrollBar,
	Rect				*scrollBarInset,
	bool				drawFocusRing,
	SInt16				inTextTraitsID,
	ClassIDT			inImpID)

	: LControlPane(inPaneInfo, inImpID, 0, 0, inTextTraitsID),
	  LCommander(inSuper),
	  mDrawFocusRing(drawFocusRing)
{
	InitDataBrowser(hasHorizonalScrollBar, hasVerticalScrollBar,
					scrollBarInset, drawFocusRing);
}



// ---------------------------------------------------------------------------
//	¥ CDataBrowser							Initializer			   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::InitDataBrowser(
	bool	hasHorizonalScrollBar,
	bool	hasVerticalScrollBar,
	Rect	*scrollBarInset,
	bool	drawFocusRing)
{
	mItemDataFunc = 0;
	mItemNotifFunc = 0;
	mDisclosureColumnID = 0;
	dispatch_flag = 0;
	
	ControlRef h = GetControlImp()->GetMacControl();
	
	::SetDataBrowserHasScrollBars(h,
								  hasHorizonalScrollBar,
								  hasVerticalScrollBar);
	if ( scrollBarInset )
		::SetDataBrowserScrollBarInset(h, scrollBarInset);
	::SetControlData(h, kControlDataBrowserPart,
					 kControlDataBrowserIncludesFrameAndFocusTag,
					 sizeof(Boolean), &drawFocusRing);
}


// ---------------------------------------------------------------------------
//	¥ ~CDataBrowser							Destructor				  [public]
// ---------------------------------------------------------------------------

CDataBrowser::~CDataBrowser()
{
	mItemDataFunc = 0;
	mItemNotifFunc = 0;
}


#pragma mark -

// ---------------------------------------------------------------------------
//	¥ SetSelectionFlag							 					  [public]
// ---------------------------------------------------------------------------

void
CDataBrowser::SetSelectionFlag(
	DataBrowserSelectionFlags	flag)
{
	ControlRef h = GetControlImp()->GetMacControl();
	OSStatus err = SetDataBrowserSelectionFlags(h, flag);
	ThrowIfError_(err);
}


// ---------------------------------------------------------------------------
//	¥ SetDisclosureColumn						 					  [public]
// ---------------------------------------------------------------------------

void
CDataBrowser::SetDisclosureColumn(
	UInt32		id)
{
	ControlRef h = GetControlImp()->GetMacControl();
	if ( mDisclosureColumnID )
	    SetDataBrowserListViewDisclosureColumn(
	    	h, mDisclosureColumnID, false);
    if ( id )
	    SetDataBrowserListViewDisclosureColumn(h, id, true);
    mDisclosureColumnID = id;
	::AutoSizeDataBrowserListViewColumns(h);
}


// ---------------------------------------------------------------------------
//	¥ AddColumn									 					  [public]
// ---------------------------------------------------------------------------
// type : kDataBrowserTextType etc.
// flag : kDataBrowserPropertyIsMutable etc.

void
CDataBrowser::AddColumn(
	UInt32			id,
	UInt32			type,
	UInt16			minWidth,
	UInt16			maxWidth,
	UInt32			flag,
	const char *	title,
	UInt32			index)
{
	ControlRef h = GetControlImp()->GetMacControl();

	DataBrowserListViewColumnDesc desc;
	desc.propertyDesc.propertyID = id;
	desc.propertyDesc.propertyType = type;
	desc.propertyDesc.propertyFlags = flag;
	desc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
	desc.headerBtnDesc.minimumWidth = minWidth;
	desc.headerBtnDesc.maximumWidth = maxWidth;
	desc.headerBtnDesc.titleOffset = 0;
	desc.headerBtnDesc.titleString = title ? CFStringCreateWithCString(
		kCFAllocatorDefault, title, CFStringGetSystemEncoding()) : 0;
	desc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
	desc.headerBtnDesc.btnFontStyle.flags = 0;
	desc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;

	OSStatus result = ::AddDataBrowserListViewColumn(h, &desc, index);
	
	if ( title )
		CFRelease(desc.headerBtnDesc.titleString);

	::AutoSizeDataBrowserListViewColumns(h);

	ThrowIfError_(result);
}


// ---------------------------------------------------------------------------
//	¥ RemoveColumn								 					  [public]
// ---------------------------------------------------------------------------

void
CDataBrowser::RemoveColumn(
	UInt32	id)
{
	ControlRef h = GetControlImp()->GetMacControl();
	OSStatus result = ::RemoveDataBrowserTableViewColumn(h, id);

	::AutoSizeDataBrowserListViewColumns(h);

	ThrowIfError_(result);
}


// ---------------------------------------------------------------------------
//	¥ AddItem									 					  [public]
// ---------------------------------------------------------------------------

OSStatus
CDataBrowser::AddItem(
	UInt32				num,
	DataBrowserItemID	*id,
	DataBrowserItemID	container)
{
	ControlRef h = GetControlImp()->GetMacControl();
	StGrafPortSaver saveAndSetPort((GrafPtr)::GetWindowPort(::GetControlOwner(h)));
	OSStatus err = AddDataBrowserItems(h, container,
						num, id, kDataBrowserItemNoProperty);
	return err;
}


// ---------------------------------------------------------------------------
//	¥ RemoveItem								 					  [public]
// ---------------------------------------------------------------------------

OSStatus
CDataBrowser::RemoveItem(
	UInt32				num,
	DataBrowserItemID	*id,
	DataBrowserItemID	container)
{
	ControlRef h = GetControlImp()->GetMacControl();
	StGrafPortSaver saveAndSetPort((GrafPtr)::GetWindowPort(::GetControlOwner(h)));
	OSStatus err = RemoveDataBrowserItems(h, container,
						num, id, kDataBrowserItemNoProperty);
	return err;
}


// ---------------------------------------------------------------------------
//	¥ UpdateItem								 					  [public]
// ---------------------------------------------------------------------------

OSStatus
CDataBrowser::UpdateItem(
	DataBrowserItemID	container,
	DataBrowserItemID	id,
	UInt32				propertyID)
{
	ControlRef h = GetControlImp()->GetMacControl();
	StGrafPortSaver saveAndSetPort((GrafPtr)::GetWindowPort(::GetControlOwner(h)));
	OSStatus err = UpdateDataBrowserItems(h, container,
						1, &id, kDataBrowserItemNoProperty, propertyID);
	return err;
}


// ---------------------------------------------------------------------------
//	¥ GetSelectedItems							 					  [public]
// ---------------------------------------------------------------------------
// caller is responsible to dispose handle outSelection

void
CDataBrowser::GetSelectedItems(
	Handle&		outSelection,
	UInt32&		outCount)
{
	ControlRef h = GetControlImp()->GetMacControl();

	outSelection = NewHandle(0);
	ThrowIfNULL_(outSelection);

	OSStatus err = GetDataBrowserItems(h, kDataBrowserNoItem, true,
										kDataBrowserItemIsSelected, outSelection);
	ThrowIfError_(err);
	
	outCount = (GetHandleSize(outSelection) /
							sizeof(DataBrowserItemID));
}

#pragma mark -

// ---------------------------------------------------------------------------
//	¥ HandleKeyPress
// ---------------------------------------------------------------------------

Boolean
CDataBrowser::HandleKeyPress( const EventRecord	&inKeyEvent )
{
	Boolean	keyHandled = true;
	UInt16	theKey = (UInt16) (inKeyEvent.message & keyCodeMask);
	UInt16	theChar = (UInt16)(inKeyEvent.message & charCodeMask)>>8;

	if (UKeyFilters::PrintingCharAndCRField(0, theKey, theChar, inKeyEvent.modifiers)  &&
                 (!(inKeyEvent.modifiers & cmdKey)) ) {
		mControlImp->DoKeyPress(inKeyEvent);
	} else {
		keyHandled = LCommander::HandleKeyPress(inKeyEvent);
	}

	return keyHandled;
}


// ---------------------------------------------------------------------------
//	¥ ObeyCommand
// ---------------------------------------------------------------------------

Boolean
CDataBrowser::ObeyCommand(
	CommandT	inCommand,
	void*		ioParam)
{
	Boolean	cmdHandled = true;

	switch (inCommand) {

		case cmd_Undo:
			ExecuteDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgUndo);
			break;
		
		case cmd_Cut:
			ExecuteDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgCut);
			break;
		
		case cmd_Copy:
			ExecuteDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgCopy);
			break;
			
		
		case cmd_Paste:
			ExecuteDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgPaste);
			break;
		
		case cmd_Clear:
			ExecuteDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgClear);
			break;

		case cmd_SelectAll:
			ExecuteDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgSelectAll);
			break;

		default:
			cmdHandled = LCommander::ObeyCommand(inCommand, ioParam);
			break;
	}

	return cmdHandled;
}


// ---------------------------------------------------------------------------
//	¥ FindCommandStatus
// ---------------------------------------------------------------------------

void
CDataBrowser::FindCommandStatus(
	CommandT	inCommand,
	Boolean		&outEnabled,
	Boolean		&outUsesMark,
	UInt16		&outMark,
	Str255		outName)
{
	switch (inCommand) {
		
		case cmd_Undo:
			outEnabled = EnableDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgUndo);
			break;
		
		case cmd_Cut:
			outEnabled = EnableDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgCut);
			break;
		
		case cmd_Copy:
			outEnabled = EnableDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgCopy);
			break;
			
		
		case cmd_Paste:
			outEnabled = EnableDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgPaste);
			break;
		
		case cmd_Clear:
			outEnabled = EnableDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgClear);
			break;

		case cmd_SelectAll:
			outEnabled = EnableDataBrowserEditCommand(
				GetControlImp()->GetMacControl(), kDataBrowserEditMsgSelectAll);
			break;

		default:
			LCommander::FindCommandStatus(inCommand, outEnabled,
									outUsesMark, outMark, outName);
			break;
	}
}

#pragma mark -

// ---------------------------------------------------------------------------
//	¥ ClickSelf													   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::ClickSelf(
	const SMouseDownEvent&	inMouseDown)
{
	if (!IsTarget())
		SwitchTarget(this);
	LControlPane::ClickSelf(inMouseDown);
}


// ---------------------------------------------------------------------------
//	¥ BeTarget													   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::BeTarget()
{
	mControlImp->BeTarget(kControlFocusNextPart);
}


// ---------------------------------------------------------------------------
//	¥ DontBeTarget												   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::DontBeTarget()
{
	mControlImp->DontBeTarget();
}


// ---------------------------------------------------------------------------
//	¥ HideSelf													   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::HideSelf()
{
	if (IsOnDuty()) {
		SwitchTarget(GetSuperCommander());
	}
	
	LControlPane::HideSelf();
}


// ---------------------------------------------------------------------------
//	¥ DisableSelf												   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::DisableSelf()
{
	if (IsOnDuty()) {
		SwitchTarget(GetSuperCommander());
	}
	
	LControlPane::DisableSelf();
}


// ---------------------------------------------------------------------------
//	¥ SpendTime													   [protected]
// ---------------------------------------------------------------------------

void
CDataBrowser::SpendTime( const EventRecord& /*inMacEvent*/ )
{
	LApplication* app = dynamic_cast<LApplication*>(LCommander::GetTopCommander());
	
	if (dispatch_flag) {
		dispatch_flag = false;
		app->DispatchEvent(reservedEvent);
	}
	else
		app->UpdateMenus();
}

#pragma mark -

// ---------------------------------------------------------------------------
//	¥ ItemDataProc						Item-Data Callback	 [static, private]
// ---------------------------------------------------------------------------

pascal OSStatus
CDataBrowser::ItemDataProc(
	ControlRef				browser,
	DataBrowserItemID		item,
	DataBrowserPropertyID	property,
	DataBrowserItemDataRef	itemData,
	Boolean					setValue)
{
	CDataBrowser *pane = (CDataBrowser*)::GetControlReference(browser);
	if (pane->mItemDataFunc)
		return pane->mItemDataFunc(pane, item, property, itemData, setValue);
	return errDataBrowserPropertyNotSupported;
}


// ---------------------------------------------------------------------------
//	¥ ItemNotificationProc		Item-Notification Callback	 [static, private]
// ---------------------------------------------------------------------------

pascal void
CDataBrowser::ItemNotificationProc(
	ControlRef					browser,
	DataBrowserItemID			item,
	DataBrowserItemNotification message)
{
	CDataBrowser *pane = (CDataBrowser*)::GetControlReference(browser);
	if (pane->mItemNotifFunc)
		pane->mItemNotifFunc(pane, item, message);
	switch (message) {
		case kDataBrowserEditStarted:
			pane->StartRepeating();
			break;
		case kDataBrowserEditStopped:
			pane->StopRepeating();
			EventRecord r;
			pane->SpendTime(r);
			break;
		case kDataBrowserContainerOpened:
			::AutoSizeDataBrowserListViewColumns(
				pane->GetControlImp()->GetMacControl());
			break;
	}
}



PP_End_Namespace_PowerPlant
