/* TextureEditorPanel::replacePatch
 * Prompts the user to select a patch from the patch table to replace
 * selectes patch(es) with
 *******************************************************************/
void TextureEditorPanel::replacePatch()
{
	// Get selection
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if no patches are selected
	if (selection.size() == 0)
		return;

	// Get first selected patch name (for browser)
	string pname = tex_canvas->getTexture()->getPatch(selection[0])->getName();

	// Browse for patch
	int patch = tx_editor->browsePatchTable(pname);
	if (patch >= 0)
	{
		// Go through selection and replace each patch
		for (size_t a = 0; a < selection.size(); a++)
			tex_current->replacePatch(selection[a], tx_editor->patchTable().patchName(patch));
	}

	// Repopulate patch list
	populatePatchList();

	// Restore selection
	for (size_t a = 0; a < selection.size(); a++)
		list_patches->selectItem(selection[a]);

	// Update UI
	updatePatchControls();

	tex_modified = true;
}
/* TextureEditorPanel::duplicatePatch
 * Duplicates selected patch(es) in the current texture (each
 * duplication is placed 8 units right+down from its original patch)
 *******************************************************************/
void TextureEditorPanel::duplicatePatch(int xoff, int yoff)
{
	// Get selection
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if no patches are selected
	if (selection.size() == 0)
		return;

	// Go through selection backwards
	for (int a = selection.size()-1; a >= 0; a--)
	{
		// Duplicate selected patch
		tex_current->duplicatePatch(selection[a], xoff, yoff);
	}

	// Repopulate patch list
	populatePatchList();

	// Update selection
	int offset = 1;
	for (size_t a = 0; a < selection.size(); a++)
	{
		list_patches->selectItem(selection[a] + offset);
		offset++;
	}

	// Update UI
	updatePatchControls();

	tex_modified = true;
}
/* TextureEditorPanel::patchBack
 * Moves selected patch(es) 'back' in the current texture
 *******************************************************************/
void TextureEditorPanel::patchBack()
{
	// Get selected patch(es)
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if nothing is selected
	if (selection.size() == 0)
		return;

	// Do nothing if first patch is selected
	if (selection[0] == 0)
		return;

	// Go through selection
	for (size_t a = 0; a < selection.size(); a++)
	{
		// Swap in list
		list_patches->swapItems(selection[a], selection[a] - 1);

		// Swap in texture
		tex_canvas->swapPatches(selection[a], selection[a] - 1);
	}

	// Update UI
	updatePatchControls();
	tex_canvas->redraw(true);

	// Restore selection in texture canvas
	selection = list_patches->selectedItems();
	for (unsigned a = 0; a < selection.size(); a++)
		tex_canvas->selectPatch(selection[a]);

	tex_modified = true;
}
/* TextureEditorPanel::patchForward
 * Moves selected patch(es) 'forward' in the current texture
 *******************************************************************/
void TextureEditorPanel::patchForward()
{
	// Get selected patch(es)
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if nothing is selected
	if (selection.size() == 0)
		return;

	// Do nothing if last patch is selected
	if (selection.back() == list_patches->GetItemCount()-1)
		return;

	// Go through selection from bottom up
	for (int a = selection.size() - 1; a >= 0; a--)
	{
		// Swap in list
		list_patches->swapItems(selection[a], selection[a] + 1);

		// Swap in texture
		tex_canvas->swapPatches(selection[a], selection[a] + 1);
	}

	// Update UI
	updatePatchControls();
	tex_canvas->redraw(true);

	// Restore selection in texture canvas
	selection = list_patches->selectedItems();
	for (unsigned a = 0; a < selection.size(); a++)
		tex_canvas->selectPatch(selection[a]);

	tex_modified = true;
}
/* TextureEditorPanel::openTexture
 * Loads a TEXTUREX format texture into the editor
 *******************************************************************/
bool TextureEditorPanel::openTexture(CTexture* tex, TextureXList* list)
{
	// Check texture was given
	if (!tex)
	{
		clearTexture();
		return false;
	}

	// Set as current texture
	if (!tex_current)
		tex_current = new CTexture();
	tex_current->copyTexture(tex);
	tex_current->setList(list);

	// Open texture in canvas
	tex_canvas->openTexture(tex_current, tx_editor->getArchive());

	// Set control values
	updateTextureControls();
	populatePatchList();
	updatePatchControls();

	tex_modified = false;

	return true;
}
/* TextureEditorPanel::removePatch
 * Removes selected patch(es) from the current texture
 *******************************************************************/
void TextureEditorPanel::removePatch()
{
	// Get selection
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if no patches are selected
	if (selection.size() == 0 )
		return;

	// Remove each selected patch
	for (int a = selection.size()-1; a >= 0; a--)
	{
		int index = selection[a];
		// Remove patch from texture
		tex_current->removePatch(index);

		// Remove patch from list
		list_patches->DeleteItem(index);
	}

	// Update UI
	updatePatchControls();
	tex_canvas->redraw(true);

	tex_modified = true;
}
/* ZTextureEditorPanel::replacePatch
 * Prompts the user to select a patch any open resource to replace
 * selectes patch(es) with
 *******************************************************************/
void ZTextureEditorPanel::replacePatch()
{
	// Get selection
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if no patches are selected
	if (selection.size() == 0)
		return;

	// Browse for patch
	string patch = tx_editor->browsePatchEntry();
	if (!patch.IsEmpty())
	{
		// Go through selection and replace each patch
		for (size_t a = 0; a < selection.size(); a++)
			tex_current->replacePatch(selection[a], patch);
	}

	// Repopulate patch list
	populatePatchList();

	// Restore selection
	for (size_t a = 0; a < selection.size(); a++)
		list_patches->selectItem(selection[a]);

	// Update UI
	updatePatchControls();

	tex_modified = true;
}
/* ZTextureEditorPanel::onTextTranslationEnter
 * Called when the enter key is pressed in the translation text box
 *******************************************************************/
void ZTextureEditorPanel::onTextTranslationEnter(wxCommandEvent& e)
{
	// Parse translation text line
	Tokenizer tz;
	tz.openString(text_translation->GetValue());
	Translation trans;

	string token = tz.getToken();
	while (!token.IsEmpty())
	{
		// Parse the translation component
		trans.parse(token);

		// Skip ,
		if (tz.peekToken() == ",")
			tz.getToken();

		// Next component
		token = tz.getToken();
	}

	// Copy updated translation to all selected patches
	wxArrayInt selection = list_patches->selectedItems();
	for (unsigned a = 0; a < selection.size(); a++)
	{
		CTPatchEx* patchx = (CTPatchEx*)tex_current->getPatch(selection[a]);
		patchx->getTranslation().copy(trans);
	}

	// Update UI
	updatePatchControls();
	tex_canvas->redraw(true);

	tex_modified = true;
}
/* TextureEditorPanel::onTexCanvasDragEnd
 * Called when a mouse drag action ends on the texture canvas
 *******************************************************************/
void TextureEditorPanel::onTexCanvasDragEnd(wxCommandEvent& e)
{
	// If patch dragging ended (left button)
	if (e.GetInt() == wxMOUSE_BTN_LEFT)
	{
		// Update patch controls
		updatePatchControls();
	}
}
/* TextureEditorPanel::onPatchListDeSelect
 * Called when a patch is deselected on the patch list
 *******************************************************************/
void TextureEditorPanel::onPatchListDeSelect(wxListEvent& e)
{
	// Deselect the patch on the texture canvas
	tex_canvas->deSelectPatch(e.GetIndex());

	// Update UI
	tex_canvas->redraw(false);
	updatePatchControls();
}
/* TextureEditorPanel::clearTexture
 * Clears the current texture
 *******************************************************************/
void TextureEditorPanel::clearTexture()
{
	// Clear texture
	if (tex_current)
		delete tex_current;
	tex_canvas->clearTexture();

	// Update variables
	tex_current = NULL;
	tex_modified = false;

	// Set control values
	updateTextureControls();
	populatePatchList();
	updatePatchControls();
}
/* TextureEditorPanel::addPatch
 * Prompts the user to select a patch from the patch table to be
 * added to the current texture
 *******************************************************************/
void TextureEditorPanel::addPatch()
{
	// Do nothing if patch list is empty
	if (tx_editor->patchTable().nPatches() == 0 || !tex_current)
		return;

	// Browse for patch
	int patch = tx_editor->browsePatchTable();
	if (patch >= 0)
	{
		// Add new patch
		tex_current->addPatch(tx_editor->patchTable().patchName(patch), 0, 0);

		// Update UI
		populatePatchList();
		updatePatchControls();
	}

	tex_modified = true;
}
/* ZTextureEditorPanel::addPatch
 * Prompts the user to select a patch from any open resources to be
 * added to the current texture
 *******************************************************************/
void ZTextureEditorPanel::addPatch()
{
	// Do nothing if no texture is open
	if (!tex_current)
		return;

	// Browse for patch
	string patch = tx_editor->browsePatchEntry();
	if (!patch.IsEmpty())
	{
		// Add new patch
		tex_current->addPatch(patch, 0, 0);

		// Update UI
		populatePatchList();
		updatePatchControls();
	}

	tex_modified = true;
}
/* ZTextureEditorPanel::onBtnEditTranslation
 * Called when the 'Edit' translation button is pressed
 *******************************************************************/
void ZTextureEditorPanel::onBtnEditTranslation(wxCommandEvent& e)
{
	// Get selected patches
	wxArrayInt selection = list_patches->selectedItems();

	// Do nothing if no patches selected
	if (selection.size() == 0)
		return;

	// Get translation from first selected patch
	Translation trans;
	CTPatchEx* patch = (CTPatchEx*)tex_current->getPatch(selection[0]);
	trans.copy(patch->getTranslation());

	// Add palette range if no translation ranges exist
	if (trans.nRanges() == 0)
		trans.addRange(TRANS_PALETTE, 0);

	// Create patch image
	SImage image(PALMASK);
	tex_canvas->getTexture()->loadPatchImage(selection[0], image, tx_editor->getArchive(), tex_canvas->getPalette());

	// Open translation editor dialog
	TranslationEditorDialog ted(theMainWindow, tex_canvas->getPalette(), "Edit Translation", &image);
	ted.openTranslation(trans);
	if (ted.ShowModal() == wxID_OK)
	{
		// Copy updated translation to all selected patches
		for (unsigned a = 0; a < selection.size(); a++)
		{
			CTPatchEx* patchx = (CTPatchEx*)tex_current->getPatch(selection[a]);
			patchx->getTranslation().copy(ted.getTranslation());
		}

		// Update UI
		updatePatchControls();
		tex_canvas->redraw(true);

		tex_modified = true;
	}
}