PortableGUI

SourceForge Logo
Hosted by SourceForge
Project page

Animate GIF's

Code for Animate app with PortableGUI

// Import all PortableGUI include files
#include <portablegui.h>

// Forward declaration
class MyAnimatedCanvas;

// Global variables
PGAnimatedImage* g_hImage = null;
MyAnimatedCanvas* g_hViewer;
PGPanel* g_hStatus;
PGFrame* g_hMainFrame;
PGLabel* g_hFrameCount;
PGLabel* g_hDelay;
PGLabel* g_hLoopCount;
PGCheckbox* g_hAnimate;
PGButton* g_hNext;
PGButton* g_hPrevious;

// Filter for opening files
char* g_sFilter = "Animated GIF Files (*.gif)$*.gif$All files (*.*)$*.*$";

// Extend the default image viewer
class MyAnimatedCanvas extends PGAnimatedImageViewer {

public:
	MyAnimatedCanvas(int w, int h, PGWindow* window) : PGAnimatedImageViewer(w, h, window) {
	}

	// Overide gotoFrame to display frame information
	virtual void gotoFrame(int idx) {
		PGString str;
		PGAnimatedImageViewer::gotoFrame(idx);
		PGAnimatedImageFrame* frame = getFrame();
		str.format("%d/%d", idx+1, getNbFrames());
		g_hFrameCount->setText(str);
		str.format("%d", frame->m_iDelay);
		g_hDelay->setText(str);
		int loops = getNbLoops();
		if (loops == 0) str.format("%d", m_iLoop);
		else str.format("%d/%d", m_iLoop, loops);
		g_hLoopCount->setText(str);
	}
	
	// Skip +1 or -1 frame
	void gotoNextPrevFrame(int delta) {
		int nb = getNbFrames();
		gotoFrame((m_iCrFrame+delta+nb) % nb);
		repaint();	
	}	
};

// Called when user selects Exit
class MyExitListener extends PGActionListener {

	virtual void actionPerformed(PGActionListenerParent* from) {		
		getPGApplication()->exit(0); 
	}
};

// Called when user tries to close the main window
class MyWindowListener extends PGWindowListener {
	
	virtual void windowClosing(PGWindow* wnd) {		
		getPGApplication()->exit(0); 
	}
};

// Called when the menu is closed
class MyMenuClosingListener extends PGMenuClosingListener {

	virtual void menuClosing(PGMenuBar* bar) {		
		g_hMainFrame->setStatus("Animate");
	}
};

// Called when user selects Open
class MyOpenListener extends PGActionListener {

	virtual void actionPerformed(PGActionListenerParent* from) {
		// Create file open dialog
		PGFileDialog dial("Open");
		dial.setFilter(g_sFilter);
		// Display file open dialog
		if (dial.showFileOpenDialog(g_hMainFrame)) {
			PGString file(dial.m_sFile);
			file.toUpperCase();
			if (file.indexOf("GIF") != -1) {
				g_hImage = new PGAnimatedImage(dial.m_sFile.getValue(), g_hMainFrame);
			} else {
				PGAnimatedImageFrame* frame = new PGAnimatedImageFrame(dial.m_sFile.getValue(), g_hMainFrame);
				frame->m_iDelay = 0;
				frame->m_iXPos = 0; 
				frame->m_iYPos = 0;				
				frame->m_iDisposalMethod = PG_DISPOSAL_NONE;	
				g_hImage = new PGAnimatedImage(g_hMainFrame);
				PGVector* frames = g_hImage->getFrames();
				g_hImage->m_iRows = frame->m_iRows;
				g_hImage->m_iCols = frame->m_iCols;
				g_hImage->m_iError = frame->m_iError;
				frames->addElement(frame);				
			}
			if (g_hImage->hasError()) {
				PGString strg;
				strg.format("Error reading animated GIF: %d", g_hImage->m_iError);
				getPGApplication()->println(strg);
			} else {
				g_hViewer->setImage(g_hImage);
				g_hViewer->startAnimation();
				g_hAnimate->setState(true);
			}
		}
	}
};

// Called when the user toggles the animate checkbox
class MyAnimateListener extends PGActionListener {

	virtual void actionPerformed(PGActionListenerParent* from) {
		boolean enable = g_hAnimate->getState();
		if (enable) g_hViewer->startAnimation();
		else g_hViewer->stopAnimation();
		g_hPrevious->setEnabled(!enable);
		g_hNext->setEnabled(!enable);
	}
};

// Called when the user clicks 'next'
class MyNextListener extends PGActionListener {

	virtual void actionPerformed(PGActionListenerParent* from) {
		g_hViewer->gotoNextPrevFrame(+1);
	}
};

// Called when the user clicks 'previous'
class MyPreviousListener extends PGActionListener {

	virtual void actionPerformed(PGActionListenerParent* from) {
		g_hViewer->gotoNextPrevFrame(-1);	
	}
};

// Make the panel with the status bar
PGPanel* makeStatus(PGFrame* frame) {
	PGPanel* panel = new PGPanel();
	panel->setLayout(new PGBorderLayout(3, 3));	
	PGLabel* status = new PGLabel("Animate", PGLABEL_SUNKEN);
	panel->add(status, PGBORDERLAYOUT_CENTER);	
	frame->add(panel, PGBORDERLAYOUT_SOUTH);
	frame->setStatusDisplay(status);
	return panel;
}

// Create panel with radio-buttons
PGPanel* makeTopPanel() {
	// Create panel
	PGPanel* panel = new PGPanel();	
	panel->setLayout(new PGPercentLayout("p 20% 80%d p", 4, 0, false));	
	PGPanel* c1 = new PGPanel();
	c1->setLayout(new PGPercentLayout("33% 33% 33%", 4, 0, true));
	c1->add(new PGLabel("Frame:"));
	c1->add(new PGLabel("Delay:"));	
	c1->add(new PGLabel("Loop:"));
	panel->add(c1);
	PGPanel* c2 = new PGPanel();
	c2->setLayout(new PGPercentLayout("33% 33% 33%", 4, 0, true));
	c2->add(g_hFrameCount = new PGLabel("0/0", PGLABEL_SUNKEN));
	c2->add(g_hDelay = new PGLabel("0", PGLABEL_SUNKEN));
	c2->add(g_hLoopCount = new PGLabel("0/0", PGLABEL_SUNKEN));
	panel->add(c2);
	PGPanel* c3 = new PGPanel();
	c3->setLayout(new PGPercentLayout("p p 100%d", 4, 0, true));
	g_hAnimate = new PGCheckbox("&Animate");
	g_hAnimate->setState(true);
	g_hAnimate->addActionListener(new MyAnimateListener());
	c3->add(g_hAnimate);
	PGPanel* c4 = new PGPanel();
	c4->setLayout(new PGPercentLayout("50% 50%", 4, 0, false));
	g_hPrevious = new PGButton("<<");
	g_hPrevious->addActionListener(new MyPreviousListener());
	g_hPrevious->setEnabled(false);	
	c4->add(g_hPrevious);
	g_hNext = new PGButton(">>");
	g_hNext->addActionListener(new MyNextListener());	
	g_hNext->setEnabled(false);
	c4->add(g_hNext);	
	c3->add(c4);
	panel->add(c3);		
	return panel;
}

// Create the main menu
PGMenuBar* makeMenu() {
	PGMenuBar* bar= new PGMenuBar();
	// Create file menu
	PGMenu* menu = new PGMenu("&File");
	PGMenuItem* item = new PGMenuItem("&Open", "Open an animation from disk");
	item->addActionListener(new MyOpenListener());
	menu->add(item);
	menu->add(new PGMenuSeparator());
	item = new PGMenuItem("&Exit", "Close Animate");
	item->addActionListener(new MyExitListener());
	menu->add(item);
	bar->add(menu);
	bar->addMenuClosingListener(new MyMenuClosingListener());
	return bar;
}

// Mainproc is different for Windows and GTK
PGMAINPROC { 
	PGApplication app;	
	PGINIT(app);
	//app.setConsoleEnabled(true);
	PGStyle* style = new PGStyle();
	style->setFont(new PGFont("Dialog", PGFONT_PLAIN, 9));
	g_hMainFrame = new PGFrame("Animate");	
	PGINCREF(g_hMainFrame);		
	g_hMainFrame->setStyle(style);	
	g_hMainFrame->addWindowListener(new MyWindowListener()); 
	g_hMainFrame->setLayout(new PGBorderLayout(4,4,3,3));
	g_hMainFrame->add(makeTopPanel(), PGBORDERLAYOUT_NORTH);
	g_hViewer = new MyAnimatedCanvas(500, 300, g_hMainFrame);
	g_hMainFrame->add(g_hViewer, PGBORDERLAYOUT_CENTER);
	g_hMainFrame->setMenuBar(makeMenu());	
	g_hStatus = makeStatus(g_hMainFrame);
	PGINCREF(g_hStatus);
	g_hMainFrame->pack(); 	
	g_hMainFrame->setVisible(true);
	PGEXITCODE exitCode = app.run();
	PGDECREF(g_hMainFrame);	
	PGDECREF(g_hStatus);
	return exitCode;
}
Syntax highlighted by Code2HTML, v. 0.9

Screenshots

How to run

Back to PortableGUI