MLPluginController::MLPluginController(MLPluginProcessor* pProcessor) :
	MLWidget::Listener(),
	MLReporter(),
	MLSignalReporter(pProcessor),
	mpView(nullptr),
	mpProcessor(pProcessor),
	mClockDivider(0),
	mConvertingPresets(false),
	mFilesConverted(0),
	mProtocolMenuItemStart(0),
	mOSCMenuItemStart(0)
{
	// initialize reference
	WeakReference<MLPluginController> initWeakReference = this;
	
	createMenu("key_scale");
	createMenu("preset");
	createMenu("settings");

	listenTo(pProcessor);
	listenTo(pProcessor->getEnvironment());
#if ML_MAC
	mFileActionData.resize(0);
	PaUtil_InitializeRingBuffer( &mFileActionQueue, sizeof(FileAction), 0, &(mFileActionData[0]) );
#endif
}
// -----------------------------------------------------------------------------
// Initialises the texture manager
// -----------------------------------------------------------------------------
void MapTextureManager::init()
{
	// Listen to the various managers
	listenTo(&App::resources());
	listenTo(&App::archiveManager());
	listenTo(theMainWindow->paletteChooser());
	palette_->copyPalette(resourcePalette());
}
MapTextureManager::MapTextureManager(Archive* archive)
{
	// Init variables
	this->archive = archive;
	editor_images_loaded = false;
	palette = new Palette8bit();

	// Listen to the various managers
	listenTo(theResourceManager);
	listenTo(theArchiveManager);
	listenTo(thePaletteChooser);
}
Exemple #4
0
/* CTextureCanvas::openTexture
 * Loads a composite texture to be displayed
 *******************************************************************/
bool CTextureCanvas::openTexture(CTexture* tex, Archive* parent)
{
	// Clear the current texture
	clearTexture();

	// Set texture
	texture = tex;
	this->parent = parent;

	// Init patches
	clearPatchTextures();
	for (uint32_t a = 0; a < tex->nPatches(); a++)
	{
		// Create GL texture
		patch_textures.push_back(new GLTexture());

		// Set selection
		selected_patches.push_back(false);
	}

	// Listen to it
	listenTo(tex);

	// Redraw
	Refresh();

	return true;
}
Exemple #5
0
/* GfxCanvas::GfxCanvas
 * GfxCanvas class constructor
 *******************************************************************/
GfxCanvas::GfxCanvas(wxWindow* parent, int id)
	: OGLCanvas(parent, id)
{
	// Init variables
	image = new SImage();
	view_type = GFXVIEW_DEFAULT;
	scale = 1;
	tex_image = new GLTexture();
	update_texture = false;
	image_hilight = false;
	drag_pos.set(0, 0);
	drag_origin.set(POINT_OUTSIDE);
	allow_drag = false;
	allow_scroll = false;
	editing_mode = 0;
	paint_colour = COL_BLACK;
	translation = NULL;
	drawing = false;
	drawing_mask = NULL;
	brush = nullptr;
	tex_brush = new GLTexture();
	cursor_pos.set(POINT_OUTSIDE);
	prev_pos.set(POINT_OUTSIDE);

	// Listen to the image for changes
	listenTo(image);

	// Bind events
	Bind(wxEVT_LEFT_DOWN, &GfxCanvas::onMouseLeftDown, this);
	Bind(wxEVT_RIGHT_DOWN, &GfxCanvas::onMouseRightDown, this);
	Bind(wxEVT_LEFT_UP, &GfxCanvas::onMouseLeftUp, this);
	Bind(wxEVT_MOTION, &GfxCanvas::onMouseMovement, this);
	Bind(wxEVT_LEAVE_WINDOW, &GfxCanvas::onMouseLeaving, this);
	Bind(wxEVT_KEY_DOWN, &GfxCanvas::onKeyDown, this);
}
// -----------------------------------------------------------------------------
// UndoListView class constructor
// -----------------------------------------------------------------------------
UndoListView::UndoListView(wxWindow* parent, UndoManager* manager) : VirtualListView{ parent }, manager_{ manager }
{
	if (manager)
	{
		SetItemCount(manager->nUndoLevels());
		listenTo(manager);
	}
}
Exemple #7
0
/* PatchTableListView::PatchTableListView
 * PatchTableListView class constructor
 *******************************************************************/
PatchTableListView::PatchTableListView(wxWindow* parent, PatchTable* patch_table) : VirtualListView(parent) {
	// Init Variables
	this->patch_table = patch_table;
	listenTo(patch_table);

	// Add columns
	InsertColumn(0, "#");
	InsertColumn(1, "Patch Name");
	InsertColumn(2, "Use Count");
	InsertColumn(3, "In Archive");

	// Update list
	updateList();

	// Listen to archive manager
	listenTo(theArchiveManager);
}
	ExternalEditFileMonitor(ArchiveEntry* entry, ExternalEditManager* manager)
		: FileMonitor("", false),
		manager(manager),
		entry(entry)
	{
		// Listen to entry parent archive
		listenTo(entry->getParent());
	}
UndoListView::UndoListView(wxWindow* parent, UndoManager* manager) : VirtualListView(parent) {
	this->manager = manager;

	if (manager) {
		SetItemCount(manager->nUndoLevels());
		listenTo(manager);
	}
}
void UndoListView::setManager(UndoManager* manager) {
	if (this->manager)
		stopListening(this->manager);

	this->manager = manager;
	listenTo(manager);

	SetItemCount(manager->nUndoLevels());
}
// -----------------------------------------------------------------------------
// Sets the undo [manager] to show in the list
// -----------------------------------------------------------------------------
void UndoListView::setManager(UndoManager* manager)
{
	if (manager_)
		stopListening(manager_);

	manager_ = manager;
	listenTo(manager);

	updateFromManager();
}
/* UndoListView::setManager
 * Sets the undo [manager] to show in the list
 *******************************************************************/
void UndoListView::setManager(UndoManager* manager)
{
	if (this->manager)
		stopListening(this->manager);

	this->manager = manager;
	listenTo(manager);

	updateFromManager();
}
float*
IMusicListener::listen(float *fft)
{
	float lineResults[NUMBER_OF_LISTENINGLINES];
	for(int i=0;i<NUMBER_OF_LISTENINGLINES;i++)
		if(Line[i].enabled)
			lineResults[i] = listenTo(i,fft);
		else
			lineResults[i] = _FNan._Float;

	return &lineResults[0];
}
Exemple #14
0
// -----------------------------------------------------------------------------
// GfxCanvas class constructor
// -----------------------------------------------------------------------------
GfxCanvas::GfxCanvas(wxWindow* parent, int id) : OGLCanvas(parent, id), scale_{ UI::scaleFactor() }
{
	// Listen to the image for changes
	listenTo(&image_);

	// Bind events
	Bind(wxEVT_LEFT_DOWN, &GfxCanvas::onMouseLeftDown, this);
	Bind(wxEVT_RIGHT_DOWN, &GfxCanvas::onMouseRightDown, this);
	Bind(wxEVT_LEFT_UP, &GfxCanvas::onMouseLeftUp, this);
	Bind(wxEVT_MOTION, &GfxCanvas::onMouseMovement, this);
	Bind(wxEVT_LEAVE_WINDOW, &GfxCanvas::onMouseLeaving, this);
	Bind(wxEVT_KEY_DOWN, &GfxCanvas::onKeyDown, this);
}
Exemple #15
0
/* BaseResourceChooser::BaseResourceChooser
 * BaseResourceChooser class constructor
 *******************************************************************/
BaseResourceChooser::BaseResourceChooser(wxWindow* parent, bool load_change)
    : wxChoice(parent, -1, wxDefaultPosition, wxSize(128, -1))
{
    // Init Variables
    this->load_change = load_change;

    // Populate
    populateChoices();

    // Listen to the archive manager
    listenTo(theArchiveManager);

    // Bind events
    Bind(wxEVT_CHOICE, &BaseResourceChooser::onChoiceChanged, this);
}
Exemple #16
0
/* ArchiveManager::addArchive
 * Adds an archive to the archive list
 *******************************************************************/
bool ArchiveManager::addArchive(Archive* archive)
{
	// Only add if archive is a valid pointer
	if (archive)
	{
		// Add to the list
		archive_t n_archive;
		n_archive.archive = archive;
		n_archive.resource = true;
		open_archives.push_back(n_archive);

		// Listen to the archive
		listenTo(archive);

		// Announce the addition
		announce("archive_added");

		// Add to resource manager
		theResourceManager->addArchive(archive);

		// ZDoom also loads any WADs found in the root of a PK3 or directory
		if ((archive->getType() == ARCHIVE_ZIP || archive->getType() == ARCHIVE_FOLDER) && auto_open_wads_root)
		{
			ArchiveTreeNode* root = archive->getRoot();
			ArchiveEntry* entry;
			EntryType* type;
			for (unsigned a = 0; a < root->numEntries(); a++)
			{
				entry = root->getEntry(a);

				if (entry->getType() == EntryType::unknownType())
					EntryType::detectEntryType(entry);

				type = entry->getType();

				if (type->getId() == "wad")
					// First true: yes, manage this
					// Second true: open silently, don't open a tab for it
					openArchive(entry, true, true);
			}
		}

		return true;
	}
	else
		return false;
}
Exemple #17
0
/* ConsolePanel::ConsolePanel
 * ConsolePanel class constructor
 *******************************************************************/
ConsolePanel::ConsolePanel(wxWindow* parent, int id)
	: wxPanel(parent, id)
{
	// Init variables
	cmd_log_index = 0;

	// Setup layout
	initLayout();

	// Listen to the console
	listenTo(theConsole);

	// Bind events
	text_command->Bind(wxEVT_COMMAND_TEXT_ENTER, &ConsolePanel::onCommandEnter, this);
	text_command->Bind(wxEVT_KEY_DOWN, &ConsolePanel::onCommandKeyDown, this);

	// Load the current contents of the console log
	text_log->AppendText(theConsole->dumpLog());
}
Exemple #18
0
// ----------------------------------------------------------------------------
// ArchiveEntryList::setArchive
//
// Sets the archive for this widget to handle (can be NULL for no archive)
// ----------------------------------------------------------------------------
void ArchiveEntryList::setArchive(Archive* archive)
{
	// Stop listening to current archive (if any)
	if (this->archive)
		stopListening(this->archive);

	// Set archive (allow null)
	this->archive = archive;

	// Init new archive if given
	if (archive)
	{
		// Listen to it
		listenTo(archive);

		// Open root directory
		current_dir = archive->getRoot();
		applyFilter();
		updateList();
	}
}
Exemple #19
0
// -----------------------------------------------------------------------------
// Adds an archive to the archive list
// -----------------------------------------------------------------------------
bool ArchiveManager::addArchive(Archive* archive)
{
	// Only add if archive is a valid pointer
	if (archive)
	{
		// Add to the list
		OpenArchive n_archive;
		n_archive.archive  = archive;
		n_archive.resource = true;
		open_archives_.push_back(n_archive);

		// Listen to the archive
		listenTo(archive);

		// Announce the addition
		announce("archive_added");

		// Add to resource manager
		theResourceManager->addArchive(archive);

		// ZDoom also loads any WADs found in the root of a PK3 or directory
		if ((archive->formatId() == "zip" || archive->formatId() == "folder") && auto_open_wads_root)
		{
			for (const auto& entry : archive->rootDir()->allEntries())
			{
				if (entry->type() == EntryType::unknownType())
					EntryType::detectEntryType(entry.get());

				if (entry->type()->id() == "wad")
					// First true: yes, manage this
					// Second true: open silently, don't open a tab for it
					openArchive(entry.get(), true, true);
			}
		}

		return true;
	}
	else
		return false;
}
Exemple #20
0
/* GfxEntryPanel::GfxEntryPanel
 * GfxEntryPanel class constructor
 *******************************************************************/
GfxEntryPanel::GfxEntryPanel(wxWindow* parent)
	: EntryPanel(parent, "gfx")
{
	// Init variables
	prev_translation.addRange(TRANS_PALETTE, 0);
	offset_changing = false;

	// Add gfx canvas
	gfx_canvas = new GfxCanvas(this, -1);
	sizer_main->Add(gfx_canvas->toPanel(this), 1, wxEXPAND, 0);
	gfx_canvas->setViewType(GFXVIEW_DEFAULT);
	gfx_canvas->allowDrag(true);
	gfx_canvas->allowScroll(true);

	// Offsets
	spin_xoffset = new wxSpinCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER, SHRT_MIN, SHRT_MAX, 0);
	spin_yoffset = new wxSpinCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER, SHRT_MIN, SHRT_MAX, 0);
	spin_xoffset->SetMinSize(wxSize(64, -1));
	spin_yoffset->SetMinSize(wxSize(64, -1));
	sizer_bottom->Add(new wxStaticText(this, -1, "Offsets:"), 0, wxALIGN_CENTER_VERTICAL, 0);
	sizer_bottom->Add(spin_xoffset, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 4);
	sizer_bottom->Add(spin_yoffset, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);

	// Gfx (offset) type
	string offset_types[] ={ "Auto", "Graphic", "Sprite", "HUD" };
	choice_offset_type = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 4, offset_types);
	choice_offset_type->SetSelection(0);
	sizer_bottom->Add(choice_offset_type, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);

	// Auto offset
	btn_auto_offset = new wxBitmapButton(this, -1, Icons::getIcon(Icons::GENERAL, "offset"));
	btn_auto_offset->SetToolTip("Modify Offsets...");
	sizer_bottom->Add(btn_auto_offset, 0, wxALIGN_CENTER_VERTICAL);

	sizer_bottom->AddStretchSpacer();

	// Aspect ratio correction checkbox
	cb_arc = new wxCheckBox(this, -1, "Aspect Ratio Correction");
	cb_arc->SetValue(gfx_arc);
	sizer_bottom->Add(cb_arc, 0, wxEXPAND, 0);
	sizer_bottom->AddSpacer(8);

	// Tile checkbox
	cb_tile = new wxCheckBox(this, -1, "Tile");
	sizer_bottom->Add(cb_tile, 0, wxEXPAND, 0);
	sizer_bottom->AddSpacer(8);

	// Image selection buttons
	btn_nextimg = new wxBitmapButton(this, -1, Icons::getIcon(Icons::GENERAL, "right"));
	btn_previmg = new wxBitmapButton(this, -1, Icons::getIcon(Icons::GENERAL, "left"));
	text_curimg = new wxStaticText(this, -1, "Image XX/XX");
	btn_nextimg->Show(false);
	btn_previmg->Show(false);
	text_curimg->Show(false);

	// Palette chooser
	listenTo(theMainWindow->getPaletteChooser());

	// Custom menu
	menu_custom = new wxMenu();
	fillCustomMenu(menu_custom);
	custom_menu_name = "Graphic";

	// Custom toolbar
	custom_toolbar_actions = "pgfx_mirror;pgfx_flip;pgfx_rotate;pgfx_translate;pgfx_colourise;pgfx_tint;pgfx_pngopt";
	setupToolbar();

	// Bind Events
	slider_zoom->Bind(wxEVT_SLIDER, &GfxEntryPanel::onZoomChanged, this);
	spin_xoffset->Bind(wxEVT_SPINCTRL, &GfxEntryPanel::onXOffsetChanged, this);
	spin_yoffset->Bind(wxEVT_SPINCTRL, &GfxEntryPanel::onYOffsetChanged, this);
	spin_xoffset->Bind(wxEVT_TEXT_ENTER, &GfxEntryPanel::onXOffsetChanged, this);
	spin_yoffset->Bind(wxEVT_TEXT_ENTER, &GfxEntryPanel::onYOffsetChanged, this);
	choice_offset_type->Bind(wxEVT_CHOICE, &GfxEntryPanel::onOffsetTypeChanged, this);
	cb_tile->Bind(wxEVT_CHECKBOX, &GfxEntryPanel::onTileChanged, this);
	cb_arc->Bind(wxEVT_CHECKBOX, &GfxEntryPanel::onARCChanged, this);
	Bind(wxEVT_GFXCANVAS_OFFSET_CHANGED, &GfxEntryPanel::onGfxOffsetChanged, this, gfx_canvas->GetId());
	btn_nextimg->Bind(wxEVT_BUTTON, &GfxEntryPanel::onBtnNextImg, this);
	btn_previmg->Bind(wxEVT_BUTTON, &GfxEntryPanel::onBtnPrevImg, this);
	btn_auto_offset->Bind(wxEVT_BUTTON, &GfxEntryPanel::onBtnAutoOffset, this);

	// Apply layout
	Layout();
}
Exemple #21
0
/* PatchTablePanel::PatchTablePanel
 * PatchTablePanel class constructor
 *******************************************************************/
PatchTablePanel::PatchTablePanel(wxWindow* parent, PatchTable* patch_table) : wxPanel(parent, -1)
{
	// Init variables
	this->patch_table = patch_table;
	this->parent = (TextureXEditor*)parent;

	// Setup sizers
	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	SetSizer(sizer);
	wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL);
	wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);

	// Add PNAMES list
	wxStaticBox* frame = new wxStaticBox(this, -1, "Patches (PNAMES)");
	wxStaticBoxSizer* framesizer = new wxStaticBoxSizer(frame, wxVERTICAL);
	sizer->Add(framesizer, 0, wxEXPAND|wxALL, 4);
	list_patches = new PatchTableListView(this, patch_table);
	list_patches->setSearchColumn(1);	// Want to search by patch name not index
	framesizer->Add(list_patches, 1, wxEXPAND|wxALL, 4);

	// Add editing controls
	sizer->Add(vbox, 1, wxEXPAND|wxALL, 4);
	vbox->Add(hbox, 0, wxEXPAND, 4);
	frame = new wxStaticBox(this, -1, "Actions");
	framesizer = new wxStaticBoxSizer(frame, wxVERTICAL);
	hbox->Add(framesizer, 0, wxEXPAND|wxALL, 4);

	// Add patch button
	btn_add_patch = new wxButton(this, -1, "New Patch");
	framesizer->Add(btn_add_patch, 0, wxEXPAND|wxALL, 4);

	// New patch from file button
	btn_patch_from_file = new wxButton(this, -1, "New Patch from File");
	framesizer->Add(btn_patch_from_file, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 4);

	// Remove patch button
	btn_remove_patch = new wxButton(this, -1, "Remove Patch");
	framesizer->Add(btn_remove_patch, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 4);

	// Change patch button
	btn_change_patch = new wxButton(this, -1, "Change Patch");
	framesizer->Add(btn_change_patch, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 4);

	// Add information display
	frame = new wxStaticBox(this, -1, "Info");
	framesizer = new wxStaticBoxSizer(frame, wxVERTICAL);
	hbox->Add(framesizer, 1, wxEXPAND|wxALL, 4);
	label_dimensions = new wxStaticText(this, -1, "Size: N/A");
	framesizer->Add(label_dimensions, 0, wxEXPAND|wxALL, 4);
	label_textures = new wxStaticText(this, -1, "In Textures: -", wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
	framesizer->Add(label_textures, 1, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 4);

	// Add patch canvas
	frame = new wxStaticBox(this, -1, "Display");
	framesizer = new wxStaticBoxSizer(frame, wxHORIZONTAL);
	vbox->Add(framesizer, 1, wxEXPAND|wxALL, 4);
	wxBoxSizer* c_box = new wxBoxSizer(wxVERTICAL);
	framesizer->Add(c_box, 1, wxEXPAND|wxALL, 4);
	patch_canvas = new GfxCanvas(this, -1);
	c_box->Add(patch_canvas->toPanel(this), 1, wxEXPAND|wxALL, 4);
	patch_canvas->setViewType(GFXVIEW_DEFAULT);
	patch_canvas->allowDrag(true);
	patch_canvas->allowScroll(true);

	// Bind events
	btn_add_patch->Bind(wxEVT_BUTTON, &PatchTablePanel::onBtnAddPatch, this);
	btn_patch_from_file->Bind(wxEVT_BUTTON, &PatchTablePanel::onBtnPatchFromFile, this);
	btn_remove_patch->Bind(wxEVT_BUTTON, &PatchTablePanel::onBtnRemovePatch, this);
	btn_change_patch->Bind(wxEVT_BUTTON, &PatchTablePanel::onBtnChangePatch, this);
	list_patches->Bind(wxEVT_LIST_ITEM_SELECTED, &PatchTablePanel::onDisplayChanged, this);

	// Palette chooser
	listenTo(theMainWindow->getPaletteChooser());
}
Exemple #22
0
	GameListener()
	{
		// Listen to archive manager
		listenTo(&App::archiveManager());
	}
// -----------------------------------------------------------------------------
// TextureXEditor class constructor
// -----------------------------------------------------------------------------
TextureXEditor::TextureXEditor(wxWindow* parent) : wxPanel(parent, -1)
{
	// Init variables
	undo_manager_ = std::make_unique<UndoManager>();
	wxWindowBase::SetName("texturex");

	// Create texture menu
	menu_texture_ = new wxMenu();
	SAction::fromId("txed_new")->addToMenu(menu_texture_);
	SAction::fromId("txed_new_patch")->addToMenu(menu_texture_);
	SAction::fromId("txed_new_file")->addToMenu(menu_texture_);
	SAction::fromId("txed_delete")->addToMenu(menu_texture_);
	menu_texture_->AppendSeparator();
	SAction::fromId("txed_rename")->addToMenu(menu_texture_);
	SAction::fromId("txed_rename_each")->addToMenu(menu_texture_);
	auto menu_export = new wxMenu();
	SAction::fromId("txed_export")->addToMenu(menu_export, "Archive (as image)");
	SAction::fromId("txed_extract")->addToMenu(menu_export, "File");
	menu_texture_->AppendSubMenu(menu_export, "&Export To");
	menu_texture_->AppendSeparator();
	SAction::fromId("txed_copy")->addToMenu(menu_texture_);
	SAction::fromId("txed_cut")->addToMenu(menu_texture_);
	SAction::fromId("txed_paste")->addToMenu(menu_texture_);
	menu_texture_->AppendSeparator();
	SAction::fromId("txed_up")->addToMenu(menu_texture_);
	SAction::fromId("txed_down")->addToMenu(menu_texture_);
	SAction::fromId("txed_sort")->addToMenu(menu_texture_);
	auto menu_patch = new wxMenu();
	SAction::fromId("txed_patch_add")->addToMenu(menu_patch);
	SAction::fromId("txed_patch_remove")->addToMenu(menu_patch);
	SAction::fromId("txed_patch_replace")->addToMenu(menu_patch);
	SAction::fromId("txed_patch_back")->addToMenu(menu_patch);
	SAction::fromId("txed_patch_forward")->addToMenu(menu_patch);
	SAction::fromId("txed_patch_duplicate")->addToMenu(menu_patch);
	menu_texture_->AppendSubMenu(menu_patch, "&Patch");

	// Create patch browser
	patch_browser_ = new PatchBrowser(theMainWindow);
	patch_browser_->CenterOnParent();
	patch_browser_->Show(false);

	// Setup sizer
	auto sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);

	// Add tabs
	tabs_ = STabCtrl::createControl(this);
	sizer->Add(tabs_, 1, wxEXPAND | wxALL, UI::pad());

	// Bind events
	Bind(wxEVT_SHOW, &TextureXEditor::onShow, this);

	// Palette chooser
	listenTo(theMainWindow->paletteChooser());
	updateTexturePalette();

	// Listen to patch table
	listenTo(&patch_table_);

	// Listen to resource manager
	listenTo(&App::resources());

	// Update + layout
	wxWindowBase::Layout();
	wxWindow::Show();
}
Exemple #24
0
// -----------------------------------------------------------------------------
// GfxEntryPanel class constructor
// -----------------------------------------------------------------------------
GfxEntryPanel::GfxEntryPanel(wxWindow* parent) : EntryPanel(parent, "gfx")
{
	// Init variables
	prev_translation_.addRange(TransRange::Type::Palette, 0);
	edit_translation_.addRange(TransRange::Type::Palette, 0);

	// Add gfx canvas
	gfx_canvas_ = new GfxCanvas(this, -1);
	sizer_main_->Add(gfx_canvas_->toPanel(this), 1, wxEXPAND, 0);
	gfx_canvas_->setViewType(GfxCanvas::View::Default);
	gfx_canvas_->allowDrag(true);
	gfx_canvas_->allowScroll(true);
	gfx_canvas_->setPalette(MainEditor::currentPalette());
	gfx_canvas_->setTranslation(&edit_translation_);

	// Offsets
	wxSize spinsize = { UI::px(UI::Size::SpinCtrlWidth), -1 };
	spin_xoffset_   = new wxSpinCtrl(
        this,
        -1,
        wxEmptyString,
        wxDefaultPosition,
        wxDefaultSize,
        wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER,
        SHRT_MIN,
        SHRT_MAX,
        0);
	spin_yoffset_ = new wxSpinCtrl(
		this,
		-1,
		wxEmptyString,
		wxDefaultPosition,
		wxDefaultSize,
		wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER,
		SHRT_MIN,
		SHRT_MAX,
		0);
	spin_xoffset_->SetMinSize(spinsize);
	spin_yoffset_->SetMinSize(spinsize);
	sizer_bottom_->Add(new wxStaticText(this, -1, "Offsets:"), 0, wxALIGN_CENTER_VERTICAL, 0);
	sizer_bottom_->Add(spin_xoffset_, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, UI::pad());
	sizer_bottom_->Add(spin_yoffset_, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, UI::pad());

	// Gfx (offset) type
	wxString offset_types[] = { "Auto", "Graphic", "Sprite", "HUD" };
	choice_offset_type_     = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 4, offset_types);
	choice_offset_type_->SetSelection(0);
	sizer_bottom_->Add(choice_offset_type_, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, UI::pad());

	// Auto offset
	btn_auto_offset_ = new SIconButton(this, "offset", "Modify Offsets...");
	sizer_bottom_->Add(btn_auto_offset_, 0, wxALIGN_CENTER_VERTICAL);

	sizer_bottom_->AddStretchSpacer();

	// Aspect ratio correction checkbox
	cb_arc_ = new wxCheckBox(this, -1, "Aspect Ratio Correction");
	cb_arc_->SetValue(gfx_arc);
	sizer_bottom_->Add(cb_arc_, 0, wxEXPAND, 0);
	sizer_bottom_->AddSpacer(UI::padLarge());

	// Tile checkbox
	cb_tile_ = new wxCheckBox(this, -1, "Tile");
	sizer_bottom_->Add(cb_tile_, 0, wxEXPAND, 0);
	sizer_bottom_->AddSpacer(UI::padLarge());

	// Image selection buttons
	btn_nextimg_ = new SIconButton(this, "right");
	btn_previmg_ = new SIconButton(this, "left");
	text_curimg_ = new wxStaticText(this, -1, "Image XX/XX");
	btn_nextimg_->Show(false);
	btn_previmg_->Show(false);
	text_curimg_->Show(false);

	// Palette chooser
	listenTo(theMainWindow->paletteChooser());

	// Custom menu
	menu_custom_ = new wxMenu();
	GfxEntryPanel::fillCustomMenu(menu_custom_);
	custom_menu_name_ = "Graphic";

	// Brushes menu
	menu_brushes_ = new wxMenu();
	fillBrushMenu(menu_brushes_);

	// Custom toolbar
	setupToolbar();

	// Bind Events
	cb_colour_->Bind(wxEVT_COLOURBOX_CHANGED, &GfxEntryPanel::onPaintColourChanged, this);
	spin_xoffset_->Bind(wxEVT_SPINCTRL, &GfxEntryPanel::onXOffsetChanged, this);
	spin_yoffset_->Bind(wxEVT_SPINCTRL, &GfxEntryPanel::onYOffsetChanged, this);
	spin_xoffset_->Bind(wxEVT_TEXT_ENTER, &GfxEntryPanel::onXOffsetChanged, this);
	spin_yoffset_->Bind(wxEVT_TEXT_ENTER, &GfxEntryPanel::onYOffsetChanged, this);
	choice_offset_type_->Bind(wxEVT_CHOICE, &GfxEntryPanel::onOffsetTypeChanged, this);
	cb_tile_->Bind(wxEVT_CHECKBOX, &GfxEntryPanel::onTileChanged, this);
	cb_arc_->Bind(wxEVT_CHECKBOX, &GfxEntryPanel::onARCChanged, this);
	Bind(wxEVT_GFXCANVAS_OFFSET_CHANGED, &GfxEntryPanel::onGfxOffsetChanged, this, gfx_canvas_->GetId());
	Bind(wxEVT_GFXCANVAS_PIXELS_CHANGED, &GfxEntryPanel::onGfxPixelsChanged, this, gfx_canvas_->GetId());
	Bind(wxEVT_GFXCANVAS_COLOUR_PICKED, &GfxEntryPanel::onColourPicked, this, gfx_canvas_->GetId());
	btn_nextimg_->Bind(wxEVT_BUTTON, &GfxEntryPanel::onBtnNextImg, this);
	btn_previmg_->Bind(wxEVT_BUTTON, &GfxEntryPanel::onBtnPrevImg, this);
	btn_auto_offset_->Bind(wxEVT_BUTTON, &GfxEntryPanel::onBtnAutoOffset, this);

	// Apply layout
	wxWindowBase::Layout();
}