PortableGUI

SourceForge Logo
Hosted by SourceForge
Project page

Graph

Code for Graph app with PortableGUI

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

// Selection modes
#define MOUSE_MODE_CLICK	0
#define MOUSE_MODE_LINE		1
#define MOUSE_MODE_RECT		2

// Drawing object types
#define DRAW_TYPE_LINE		0
#define DRAW_TYPE_ARC		1
#define DRAW_TYPE_ROUNDRECT	2
#define DRAW_TYPE_STAR		3
#define DRAW_TYPE_LOGO		4
#define DRAW_TYPE_TEXT		5

// Forward declaration
class MyCanvas;

// Main frame window
PGFrame* g_hMainFrame;
// Status bar
PGPanel* g_hStatus;
// PortableGUI Logo
PGImage* g_hLogo;
// For drawing
MyCanvas* g_hMyCanvas;
// Object array
PGVector* g_hObjects;
// Size for lines
PGIntegerField* g_hLineSize;
// Radion button groups
PGButtonGroup* m_hGroup1;
PGButtonGroup* m_hGroup2;
// Mouse rectangle position
int g_iStartX, g_iStartY;
int g_iPrevX, g_iPrevY;
// Mode for selection
int g_iMode = MOUSE_MODE_LINE;
// Colors for drawing objects
PGColor* g_hColors[] = {
		PGCOLOR_BLACK, PGCOLOR_BLUE, PGCOLOR_GRAY, PGCOLOR_GREEN,
		PGCOLOR_ORANGE, PGCOLOR_RED, PGCOLOR_WHITE, PGCOLOR_YELLOW
};

// An object that can be drawn on our canvas
class MyDrawObject : public PGObject {
protected:
	int m_iX1, m_iY1;	
	int m_iColor;
public:
	// Construct a new drawable object
	MyDrawObject(int x, int y, int color) {
		m_iX1 = x;
		m_iY1 = y;
		m_iColor = color;
	}
	
	// Draw the object on screen
	virtual void draw(PGGraphics* graph) {               
	       graph->setColor(g_hColors[m_iColor]);
	       graph->setLineWidth(1);
	}
};	

// A line that can be drawn on our canvas
class MyDrawObjectLine : public MyDrawObject {
protected:
	int m_iX2, m_iY2, m_iSize;
public:
	// Construct a new drawable line
	MyDrawObjectLine(int x1, int y1, int x2, int y2, int siz, int col) : MyDrawObject(x1, y1, col) {
		m_iX2 = x2;
		m_iY2 = y2;
		m_iSize = siz;
	}
	
	// Draw the line on screen
	virtual void draw(PGGraphics* graph) {               
	       MyDrawObject::draw(graph);
	       graph->setLineWidth(m_iSize);
	       graph->drawLine(m_iX1, m_iY1, m_iX2, m_iY2);
	}		
};

// An arc that can be drawn on our canvas
class MyDrawObjectArc : public MyDrawObject {
protected:
	int m_iWidth, m_iHeight;
public:
	// Construct a new drawable arc
	MyDrawObjectArc(int x1, int y1, int wd, int hi, int col) : MyDrawObject(x1, y1, col) {
		m_iWidth  = wd;
		m_iHeight = hi;
	}
	
	// Draw the arc on screen
	virtual void draw(PGGraphics* graph) {               
		MyDrawObject::draw(graph);
	     	graph->fillArc(m_iX1, m_iY1, m_iWidth, m_iHeight, 45, 315);  
	}		
};

// A rectangle with rounded corners that can be drawn on our canvas
class MyDrawObjectRoundRect : public MyDrawObject {
protected:
	int m_iWidth, m_iHeight;
public:
	// Construct a new drawable rounded rectanlge
	MyDrawObjectRoundRect(int x1, int y1, int wd, int hi, int col) : MyDrawObject(x1, y1, col) {
		m_iWidth  = wd;
		m_iHeight = hi;
	}
	
	// Draw the rounded rectangle on screen
	virtual void draw(PGGraphics* graph) {               
		MyDrawObject::draw(graph);
		graph->fillRoundRect(m_iX1, m_iY1, m_iWidth, m_iHeight, 20, 20);  
	}		
};

// A star that can be drawn on our canvas
class MyDrawObjectStar : public MyDrawObject {
protected:
	PGPolygon* m_hPoly;
public:
	// Construct a new drawable star
	MyDrawObjectStar(int x1, int y1, int wd, int hi, int col) : MyDrawObject(x1, y1, col) {
		m_hPoly = makeStar(x1, y1, wd, hi);
		PGINCREF(m_hPoly);
	}
	
	// Terminate object
	virtual ~MyDrawObjectStar() {
		PGDECREF(m_hPoly);
	}
	
	// Create a polygon in the shape of a star
	PGPolygon* makeStar(int x, int y, int xl, int yl) {
		PGPolygon* poly = new PGPolygon(10);
		poly->addPoint(x+xl/2,y);                  /*1*/
            	poly->addPoint(x+xl*100/155,y+yl*45/150);  /*2*/
            	poly->addPoint(x+xl,y+yl*45/150);          /*3*/
            	poly->addPoint(x+xl*115/155,y+yl*75/150);  /*4*/
            	poly->addPoint(x+xl,y+yl);                 /*5*/
            	poly->addPoint(x+xl/2,y+yl*10/15);         /*6*/
            	poly->addPoint(x,y+yl);                    /*7*/
            	poly->addPoint(x+xl*40/155,y+yl*75/150);   /*8*/
            	poly->addPoint(x,y+yl*45/150);             /*9*/
            	poly->addPoint(x+xl*55/155,y+yl*45/150);   /*A*/		
		return poly;
	}
	
	// Draw the star on screen
	virtual void draw(PGGraphics* graph) {               
		MyDrawObject::draw(graph);
	     	graph->fillPolygon(m_hPoly);
	}		
};

// PortableGUI logo that can be drawn on our canvas
class MyDrawObjectLogo : public MyDrawObject {
public:
	// Construct a new drawable PortableGUI logo
	MyDrawObjectLogo(int x1, int y1, int col) : MyDrawObject(x1, y1, col) {
	}
	
	// Draw the PortableGUI logo on screen
	virtual void draw(PGGraphics* graph) {               
	       MyDrawObject::draw(graph);
	       graph->drawImage(g_hLogo, m_iX1, m_iY1);
	}		
};

// The text 'PortableGUI' that can be drawn on our canvas
class MyDrawObjectText : public MyDrawObject {
protected:
	PGFont* m_hFont;
public:
	// Construct a new drawable text
	MyDrawObjectText(int x1, int y1, int wd, int hi, int col) : MyDrawObject(x1, y1, col) {
		m_hFont = makeFont(wd, hi);
		PGINCREF(m_hFont);
	}
	
	// Terminate object
	virtual ~MyDrawObjectText() {
		PGDECREF(m_hFont);
	}
	
	// Create the font depending on the width and height
	PGFont* makeFont(int w, int h) {
		int size = PGMathMin(w/15, h/4)*2;
		size = PGMathMax(size, 8);
		size = PGMathMin(size, 40);		
		return new PGFont("Times", PGFONT_BOLD, size);		
	}		
	
	// Draw the text on screen
	virtual void draw(PGGraphics* graph) {               
		MyDrawObject::draw(graph);
	     	graph->setFont((PGNormalComponent*)g_hMyCanvas, m_hFont);
		graph->drawString("PortableGUI", m_iX1, m_iY1);
	}		
};

// Canvas for drawing the picture
class MyCanvas : public PGDoubleBufferCanvas {
public:
	// Return the preferred size for this component
	virtual void getPreferredSize(PGDimension* dimension, BOOL recalc) {
		dimension->width = 500;
		dimension->height = 400;
	}

	// Paint all objects
	virtual void draw(PGGraphics* graph) {
		// Get size
		PGDimension dim;
		getSize(&dim);		
		// Draw background
		graph->setColor(PGCOLOR_DARKGRAY);
		graph->fillRect(0, 0, dim.width, dim.height);				
		// Draw objects
		for (int ctr = 0; ctr < g_hObjects->getSize(); ctr++) {
			MyDrawObject* obj = (MyDrawObject*)g_hObjects->getElementAt(ctr);
			obj->draw(graph);
		}		
	}

	// Redraw region painted when mouse-drags
	void redrawDragRegion() {				
		PGRectangle rect;
		updateDragRegion(&rect);
		drawDragRegion(&rect);
	}
	
	// Update region painted when mouse-drags
	PGGraphics* updateDragRegion(PGRectangle* rect) {		
		// Get buffer graphics		
		PGGraphics* bufGrp = getBufferGraphics();
		// Set right clip
		rect->fromPoints(g_iStartX, g_iStartY, g_iPrevX, g_iPrevY);		
		bufGrp->setClip(rect->x-2, rect->y-2, rect->width+4, rect->height+4);		
		draw(bufGrp);
		return bufGrp;
	}	
	
	// Draw region painted when mouse-drags
	void drawDragRegion(PGRectangle* rect) {		
		PGGraphics graph;
		getGraphics(&graph);		
		rect->fromPoints(g_iStartX, g_iStartY, g_iPrevX, g_iPrevY);
		redraw(rect->x-2, rect->y-2, rect->width+4, rect->height+4, &graph);		
	}
};

// Canvas for the color chooser
class MyColorCanvas : public PGCanvas {
private:
	PGColor* m_Color;	
public:
	// Create a new color chooser canvas
	MyColorCanvas(PGColor* color) {
		m_Color = color;
	}

	// Return the preferred size for this component
	virtual void getPreferredSize(PGDimension* dimension, BOOL recalc) {
		dimension->width = 30;
		dimension->height = 15;
	}

	// Paint the color in a dark gray rectangle
	virtual void paint(PGGraphics* graph) {
		PGDimension dim;
		getSize(&dim);
		graph->setColor(m_Color);
		graph->fillRect(0, 0, dim.width, dim.height);		
		graph->setColor(PGCOLOR_DARKGRAY);
		graph->drawRect(0, 0, dim.width, dim.height);		
	}	
};

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

// Called when the user chooses another tool
class MyToolListener : public PGActionListener {
private:
	char* m_sStatus;
	int m_iMode;
public:	
	// Create a listener for a tool radio-button
	MyToolListener(const char* status, int mode) {
		m_sStatus = (char*)status;
		m_iMode = mode;
	} 
	
	// Update status-bar and change drag mode
	virtual void actionPerformed(PGActionListenerParent* from) {
		g_iMode = m_iMode;
		g_hMainFrame->setStatus(m_sStatus);
	}
};

// Respond to mouse events
class MyMouseListener : public PGMouseListener {
	
	// Add an object to the canvas
	void addObject(int x, int y, int w, int h) {
		BOOL update = FALSE;
		// Get type and color from radio button groups
		int type = m_hGroup1->getSelectedIndex();
		int col = m_hGroup2->getSelectedIndex();
		// Create the drawable object
		MyDrawObject* obj = (MyDrawObject*)NULL;
		switch (type) {		
			case DRAW_TYPE_LINE:
				obj = new MyDrawObjectLine(x, y, w, h, g_hLineSize->getValue(), col);
				update = TRUE;
				break;
			case DRAW_TYPE_ARC:
				obj = new MyDrawObjectArc(x, y, w, h, col);
				break;	
			case DRAW_TYPE_ROUNDRECT:
				obj = new MyDrawObjectRoundRect(x, y, w, h, col);
				break;
			case DRAW_TYPE_STAR:		
				obj = new MyDrawObjectStar(x, y, w, h, col);
				break;
			case DRAW_TYPE_LOGO:	
				obj = new MyDrawObjectLogo(x, y, col);
				update = TRUE;	
				break;
			case DRAW_TYPE_TEXT:
				obj = new MyDrawObjectText(x, y, w, h, col);
				update = TRUE;
				break;
		}				
		// Add the object
		g_hObjects->addElement(obj);
		if (update) {
			g_hMyCanvas->repaint();		
		} else {
			g_hMyCanvas->redrawDragRegion();			
		}
	}

	// Select origin
	virtual void mousePressed(PGMouseEvent* e) {		
		g_iStartX = e->getX();
		g_iStartY = e->getY();
		g_iPrevX = g_iStartX;
		g_iPrevY = g_iStartY;
		if (g_iMode == MOUSE_MODE_CLICK) 
			addObject(g_iStartX, g_iStartY, 0, 0);
	}
	
	// Draw object
	virtual void mouseReleased(PGMouseEvent* e) {		
		if (g_iMode != MOUSE_MODE_CLICK) {			
			PGRectangle rect;
			if (g_iMode == MOUSE_MODE_RECT) {
				// Rectangle drawing mode
				rect.fromPoints(g_iStartX, g_iStartY, g_iPrevX, g_iPrevY);
			} else {
				// Line drawing mode
				rect.x = g_iStartX;
				rect.y = g_iStartY;
				rect.width  = g_iPrevX;
				rect.height = g_iPrevY;
			}			
			addObject(rect.x, rect.y, rect.width, rect.height);
		}
	}

	// FIXME: The mouseExit message is not available yet	
	virtual void mouseExited(PGMouseEvent* e) {
		getPGApplication()->println("Exit rgn");
		if (g_iMode != MOUSE_MODE_CLICK) g_hMyCanvas->redrawDragRegion();		
	}	
	
};

// Respond to mouse motion events
class MyMouseMotionListener : public PGMouseMotionListener {

	// Mouse is dragged
	virtual void mouseDragged(PGMouseEvent* e) {
		if (g_iMode != MOUSE_MODE_CLICK) {											
			PGRectangle rect;
			PGGraphics* graph = g_hMyCanvas->updateDragRegion(&rect);			
			// Draw rect or line in white
			graph->setColor(PGCOLOR_WHITE);			
			graph->setLineWidth(1);
			if (g_iMode == MOUSE_MODE_RECT) {
				PGRectangle rect;
				rect.fromPoints(g_iStartX, g_iStartY, e->getX(), e->getY());		
				graph->drawRect(rect.x, rect.y, rect.width, rect.height);		
			} else {
				graph->drawLine(g_iStartX, g_iStartY, e->getX(), e->getY());
			}
			g_hMyCanvas->drawDragRegion(&rect);			
			// Remember previous point
			g_iPrevX = e->getX();
			g_iPrevY = e->getY();			
		}
	}

};

// Create panel with radio-buttons
PGPanel* makeLeftPanel() {
	// Create a buttongroup for the radio buttons
	PGRadioButton* rdbutton;
	m_hGroup1 = new PGButtonGroup();
	m_hGroup2 = new PGButtonGroup();	
	// Create panel	 
	PGPanel* panel = new PGPanel();	
	panel->setLayout(new PGPercentLayout("p p p p p p 10%d p 90%d p p p p p p p p", 4, 0, TRUE));	
	// Add tool buttons
	panel->add(rdbutton = new PGRadioButton("Line"));
	rdbutton->setToolTipText("Draw a line");
	rdbutton->addActionListener(new MyToolListener("Drag to draw a line", MOUSE_MODE_LINE));
	m_hGroup1->add(rdbutton);	
	panel->add(rdbutton = new PGRadioButton("Arc"));
	rdbutton->setToolTipText("Draw a an arc");
	rdbutton->addActionListener(new MyToolListener("Drag to draw an arc", MOUSE_MODE_RECT));
	m_hGroup1->add(rdbutton);
	panel->add(rdbutton = new PGRadioButton("RoundRect"));
	rdbutton->setToolTipText("Draw a rectangle with rounded corners");
	rdbutton->addActionListener(new MyToolListener("Drag to draw a rectangle with rounded corners", MOUSE_MODE_RECT));
	m_hGroup1->add(rdbutton);
	panel->add(rdbutton = new PGRadioButton("Star"));
	rdbutton->setToolTipText("Draw a star");
	rdbutton->addActionListener(new MyToolListener("Drag to draw a star", MOUSE_MODE_RECT));
	m_hGroup1->add(rdbutton);	
	panel->add(rdbutton = new PGRadioButton("Logo"));
	rdbutton->setToolTipText("Draw the PortableGUI logo");
	rdbutton->addActionListener(new MyToolListener("Click to draw the PortableGUI logo", MOUSE_MODE_CLICK));
	m_hGroup1->add(rdbutton);		
	panel->add(rdbutton = new PGRadioButton("PortableGUI"));
	rdbutton->setToolTipText("Draw the text 'PortableGUI'");
	rdbutton->addActionListener(new MyToolListener("Drag to draw the text 'PortableGUI'", MOUSE_MODE_RECT));
	m_hGroup1->add(rdbutton);			
	// Add the line size button		
	PGPanel *entries = new PGPanel();
	entries->setLayout(new PGBorderLayout(3, 3));
	g_hLineSize = new PGIntegerField(1);
	g_hLineSize->setToolTipText("Set the width for drawing lines");
	entries->add(g_hLineSize, PGBORDERLAYOUT_CENTER);		
	entries->add(new PGUpDown(g_hLineSize, 1, 4, 1), PGBORDERLAYOUT_EAST);
	panel->add(entries);		
	// Add color buttons		
	for (int color = 0; color < 8; color++) {
		PGPanel* subpanel = new PGPanel();
		subpanel->setLayout(new PGBorderLayout(0, 0));		
		subpanel->add(rdbutton = new PGRadioButton(), PGBORDERLAYOUT_WEST);	
		m_hGroup2->add(rdbutton);
		subpanel->add(new MyColorCanvas(g_hColors[color]), PGBORDERLAYOUT_CENTER);			
		panel->add(subpanel);
	}	
	return panel;
}

// Make the panel with the status bar
PGPanel* makeStatus(PGFrame* frame, PGImage* file) {
	// Create style for status line
	PGStyle* style = new PGStyle();
	style->setFont(new PGFont("Dialog", PGFONT_PLAIN, 8));
	// Create panel
	PGPanel* panel = new PGPanel();
	panel->setLayout(new PGBorderLayout(3, 3));	
	// Create and add status line
	PGLabel* status = new PGLabel("Graphics", PGLABEL_SUNKEN);	
	status->setStyle(style);	
	panel->add(status, PGBORDERLAYOUT_CENTER);	
	// Add icon
	panel->add(new PGImageViewer(file), PGBORDERLAYOUT_EAST);
	// Add panel to main frame
	frame->add(panel, PGBORDERLAYOUT_SOUTH);
	frame->setStatusDisplay(status);
	return panel;
}

// Mainproc is different for Windows and GTK
PGMAINPROC { 
	PGApplication app;	
	// Initialize the app using Mainproc args
	PGINIT(app);
	
	app.setConsoleEnabled(TRUE);
		
	// Create array for objects 	
	g_hObjects = new PGVector();
	PGINCREF(g_hObjects);
	// Create main frame window
	g_hMainFrame = new PGFrame("PGGraphics");
	PGINCREF(g_hMainFrame);	
	// Load icon for main window	
	PGColor background(178,178,180);	
	PGImage* file = new PGImage("../../images/file.bmp", &background, g_hMainFrame);	
	g_hMainFrame->setIconImage(new PGIcon(file));
	// Load PortableGUI logo	
	g_hLogo = new PGImage("../../images/logo.bmp", PGCOLOR_YELLOW, g_hMainFrame);
	PGINCREF(g_hLogo);
	// Add window listener to frame
	g_hMainFrame->addWindowListener(new MyWindowListener()); 
	// Use simple layoutmanager for the edit control
	g_hMainFrame->setLayout(new PGBorderLayout(1,1,3,3));
	// Add the panel with the radio-buttons
	g_hMainFrame->add(makeLeftPanel(), PGBORDERLAYOUT_WEST);
	// Add the drawing canvas
	g_hMyCanvas = new MyCanvas();
	g_hMyCanvas->addMouseListener(new MyMouseListener());
	g_hMyCanvas->addMouseMotionListener(new MyMouseMotionListener());
	g_hMainFrame->add(g_hMyCanvas, PGBORDERLAYOUT_CENTER);
	// Make and add status bar	
	g_hStatus = makeStatus(g_hMainFrame, new PGImage("../../images/resize.bmp", &background, g_hMainFrame));
	PGINCREF(g_hStatus);
	// Pack and show the frame
	g_hMainFrame->pack(); 	
	g_hMainFrame->setVisible(TRUE);
	// Run the main event loop	
	PGEXITCODE exitCode = app.run();
	// Free global references
	PGDECREF(g_hObjects);			
	PGDECREF(g_hMainFrame);
	PGDECREF(g_hLogo);
	PGDECREF(g_hStatus);
	return exitCode;
}
Syntax highlighted by Code2HTML, v. 0.9

Screenshots

How to run

Back to PortableGUI