AeAssetEditor.c++ 6.06 KB
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <Xm/Xm.h>
#include <Vk/VkQuestionDialog.h>

#include "GList.h"
#include "AeAssetEditor.h"
#include "AeAssetBase.h"
#include "AeAssetBin.h"
#include "AeAssetBinUI.h"
#include "AeAssetUI.h"
#include "AeAssetWindow.h"
#include "AeBinView.h"
#include "AePlayer.h"
#include "AeN64Driver.h"
#include "AeFile.h"
#include "AeInstFile.h"
#include "AeBankEditor.h"
#include "AeErr.h"


AeAssetEditor::AeAssetEditor (void) : AeBinEditor ()
{
    fWindow = NULL;
    fFile = NULL;
    fSaveNeeded = False;
}


AeAssetEditor::~AeAssetEditor (void)
{
    if (fWindow)
	delete fWindow;

    if (fFile)
	delete fFile;
}


void
AeAssetEditor::SetAssetBase (AeAssetBase * assetBase)
{
    assert (assetBase);		// must be non-NULL

    AeBinEditor::SetAssetBase (assetBase);

    // create and init all the UI objects for this editor
    createBinUIs ();
    initBinUIs ();
    createAssetUIs ();
    initChildBinUIs ();

    // default to editing the first bin in the list
    fBinUI = (*fBinUIList)[0];

    // now that we have data, create a window to display it
    fWindow = new AeAssetWindow ("Asset Catalog", this);
    fWindow->show();

    fView = fWindow->GetView ();
    fView->TabSetLabels ();		// update the view's bin labels

    if (fPlayer)
	fPlayer->BuildMenu (fWindow);
}


void
AeAssetEditor::CreateAsset (AeAsset * asset, Boolean suspended)
{
    if (asset->IsBankComponent ())
	fSaveNeeded = True;

    AeBinEditor::CreateAsset (asset, suspended);
}


void
AeAssetEditor::UpdateAsset (AeAsset * asset, Boolean suspended)
{
    if (asset->IsBankComponent ())
	fSaveNeeded = True;

    AeBinEditor::UpdateAsset (asset, suspended);
}


void
AeAssetEditor::DeleteAsset (AeAsset * asset, Boolean suspended)
{
    if (asset->IsBankComponent ())
	fSaveNeeded = True;

    AeBinEditor::DeleteAsset (asset, suspended);
}


void
AeAssetEditor::SaveFile (void)
{
    AeErr err;

    assert (fFile);

    if (fFile)
    {
	if (!(err = fFile->Write (fAssetBase)))
	    fSaveNeeded = False;
    }
}


void
AeAssetEditor::SaveAsFile (const char * name)
{
    if (fFile)
	fFile->SetFullName ((char *)name);
    else
	fFile = (AeAssetFile *)new AeInstFile ((char *)name);

    if (fFile)
    {
	SaveFile ();
 	fView->setTitle (fFile->GetFileName ());
   }
}


//
// This routine opens and reads the named file
// and if successful, it adds its assets to the database
// and saves the file reference.
//
void
AeAssetEditor::OpenFile (const char * name)
{
    AeAssetFile * file;
    AeAsset * asset;

    if (fFile)
	CloseFile ();

    assert (fFile == NULL);

    if (file = getAndReadFile (name, False))
    {
	fFile = file;
	fView->setTitle (fFile->GetFileName ());
    }

    fSaveNeeded = False;
}


void
AeAssetEditor::CloseFile (void)
{
    // if there's a file, see if the user wants it saved
    if (fFile)
    {
	if (fSaveNeeded)
	{
	    AeDialogReply reply = postSaveQuestion ();

	    if (reply == CANCEL)
		return;

	    if (reply == YES)
		SaveFile ();
	}
    }

    // delete all the bank assets and specially notify the player
    DeleteAllBankAssets ();
    ((AeN64Driver *)fPlayer)->CloseBank ();	// hack

    // if there is a file, then delete it
    if (fFile)
    {
	delete fFile;
	fFile = NULL;
	fSaveNeeded = False;
    }
}


//
// Import assets from the given file name.
// Some files, like inst files, don't need to 
// keep the file object around so it can be deleted.
// But other files, like wave files, need their
// file object so it can't be deleted.  For now
// never delete the file object, although we're
// wasting memory when importing inst files.
//
void
AeAssetEditor::ImportAsset (const char * name)
{
    getAndReadFile (name, True);
}


//
// Open an asset-specific editor.
//
void
AeAssetEditor::OpenEditor (AeAsset * asset)
{
    AeEditor *	editor;

    switch (asset->GetType ())
    {
	case kBankType:
	    editor = (AeEditor *)new AeBankEditor;
	    editor->SetAssetBase (fAssetBase);
	    ((AeBankEditor *)editor)->SetBankAsset ((AeBankAsset *)asset);
	break;
    }
}


//
// create a new file based on the name and
// then read the file and add its assets to
// the asset base.  if an error occurs, abort
// the whole process by deleting the file and
// returning NULL.
//
AeAssetFile *
AeAssetEditor::getAndReadFile (const char * name, Boolean importing)
{
    AeAssetFile * 	file;
    GList<AeAsset *> * 	assetList = NULL;

    if (file = AeAssetFile::NewAssetFile ((char *)name))
    {
	if (file->ReadList (assetList) == kAeNoErr)
	{
	    if (importing)
		removeBankAsset (assetList);

	    fAssetBase->NotifySuspend ();
	    fAssetBase->AppendAssetList (assetList);
	    fAssetBase->NotifyResume ();
	}
	else
	{
	    delete file;
	    file = NULL;
	}
    }

    if (assetList)
	delete assetList;

    return file;
}	


void
AeAssetEditor::removeBankAsset (GList<AeAsset *> * list)
{
    AeAsset * asset;
    int	i;

    list->Start (i);
    while (list->Next (i, asset))
    {
	if (asset->GetType () == kBankType)
	{
	    list->Remove (asset);
	    break;
	}
    }
}


Boolean
AeAssetEditor::binHasUI (AeAssetBin * bin)
{
    switch (bin->GetType ())
    {
	case kLoopType:
	case kADPCMBookType:
	    return False;
    }

    return True;
}


void
AeAssetEditor::createAssetUIs (void)
{
    GList<AeAssetBin *> *	binList;
    AeAssetBin *		bin;
    GList<AeAsset *> * 		assetList;
    AeAsset *			asset;
    int		       		i, j;

    binList = fAssetBase->GetBinList ();
    binList->Start (i);

    while (binList->Next (i, bin))
    {
	assetList = bin->GetAssetList ();
	assetList->Start (j);

	while (assetList->Next (j, asset))
	    createAssetUI (asset);
    }
}


AeAssetEditor::AeDialogReply
AeAssetEditor::postSaveQuestion (void)
{
    VkDialogManager::VkDialogReason	reason;
    AeDialogReply			reply;

    theQuestionDialog->setTitle ("Unsaved Changes");
    theQuestionDialog->setButtonLabels ("Yes", "Cancel", "No");

    reason = theQuestionDialog->postAndWait ("Save changes before closing?",
					     TRUE, TRUE, TRUE);

    if (reason == VkDialogManager::OK)
	reply = YES;

    else if (reason == VkDialogManager::APPLY)
	reply = NO;

    else
	reply = CANCEL;

    return reply;
}