Power of Pink - a dinamic square/button solution with 1 png


#1

I finally got it working, and it works out great. I hope there’s no bug on the code, but if someone finds anything, please, let me know. :oops:

Download files at the following link:
http://www.wusik.com/w/juce.html

I will post the code in the next post.


#2

The idea was taken from Reaper solution for the png files.

Here we have a single png file with 2 button states: normal and clicked. And the pink lines determinate the corners of the image that are fixed. From this, we get 9 images, likes this:

0 1 2 3 4 5 6 7 8

So we can draw a square/rectangle of any size.


#3

Header code:

[code]/*
Created by WilliamK @ Wusik Dot com © 2009
*/

//-----------------------------------------------------------------------------------------------------------
class JUCE_API NewLookAndFeel : public LookAndFeel, DeletedAtShutdown
{
public:
NewLookAndFeel();
~NewLookAndFeel();

juce_DeclareSingleton (NewLookAndFeel,false)

static void drawImageSquare(Graphics& g,Image** images,int x,int y,int width,int height,float opacity);
static void stripPinkImage(Image* original, Image** destination, int height = 0, int offsetY = 0);

};

#endif[/code]


#4

Main code:

[code]/*
Created by WilliamK @ Wusik Dot com © 2009
*/

//-----------------------------------------------------------------------------------------------------------
void NewLookAndFeel::stripPinkImage(Image* original, Image** destination, int height, int offsetY)
{
if (height == 0) height = original->getHeight();
int x=0;
int Corners[4] = {0,0,0,0}; // Top-Left X and Y, Bottom-Right X and Y //
Colour cPink = Colour::fromString(T(“ffff00ff”));

for (x=0; x<original->getWidth(); x++) { if (original->getPixelAt(x,offsetY) != cPink) break; Corners[0] = x-1; }
for (x=0; x<height; x++) { if (original->getPixelAt(0,x+offsetY) != cPink) break; Corners[1] = x-1; }
		
for (x=original->getWidth()-1; x>=0; x--) { if (original->getPixelAt(x,height-1+offsetY) != cPink) break; Corners[2] = x-2; }
for (x=(height-1); x>=0; x--) { if (original->getPixelAt(original->getWidth()-1,x+offsetY) != cPink) break; Corners[3] = x-2; }
					
/*	0	1	2
	3	4	5
	6	7	8
*/

// Create Buttons //
int bW = original->getWidth()-2;
int bH = height-2;
#define CreateBT(BT,W,H) destination[BT] = new Image(Image::ARGB,W,H,true);

CreateBT(0, Corners[0], Corners[1]);
CreateBT(1, Corners[2]-Corners[0], Corners[1]);
CreateBT(2, bW-Corners[2], Corners[1]);
//
CreateBT(3, Corners[0], Corners[3]-Corners[1]);
CreateBT(4, Corners[2]-Corners[0], Corners[3]-Corners[1]);
CreateBT(5, bW-Corners[2], Corners[3]-Corners[1]);
//
CreateBT(6, Corners[0], bH-Corners[3]);
CreateBT(7, Corners[2]-Corners[0], bH-Corners[3]);
CreateBT(8, bW-Corners[2], bH-Corners[3]);

// Perform Copies //
int y=0;
int pX = 0;
int pY = 0;

for (int bt=0; bt<9; bt++)
{
	switch(bt)
	{
		case 1:	pX = Corners[0];	pY = 0;				break;
		case 2:	pX = Corners[2];	pY = 0;				break;
		case 3:	pX = 0;				pY = Corners[1];	break;
		case 4:	pX = Corners[0];	pY = Corners[1];	break;
		case 5:	pX = Corners[2];	pY = Corners[1];	break;
		case 6:	pX = 0;				pY = Corners[3];	break;
		case 7:	pX = Corners[0];	pY = Corners[3];	break;
		case 8:	pX = Corners[2];	pY = Corners[3];	break;
	}

	for (y=0; y<destination[bt]->getHeight(); y++)
	{
		for (x=0; x<destination[bt]->getWidth(); x++)
		{
			destination[bt]->setPixelAt(x,y,original->getPixelAt(x+1+pX,y+1+pY+offsetY));
		}
	}
}

}

//-----------------------------------------------------------------------------------------------------------
void NewLookAndFeel::drawImageSquare(Graphics& g,Image** images,int x,int y,int width,int height,float opacity)
{
g.setTiledImageFill(*images[4],x+images[3]->getWidth(),y+images[1]->getHeight(),opacity);
g.fillRect(x+images[3]->getWidth(),y+images[1]->getHeight(),width-images[3]->getWidth()-images[5]->getWidth(), height-images[1]->getHeight()-images[7]->getHeight());

g.setTiledImageFill(*images[1],x+images[0]->getWidth(),y,opacity);
g.fillRect(x+images[0]->getWidth(),y,width-images[0]->getWidth()-images[2]->getWidth(),images[1]->getHeight());

g.setTiledImageFill(*images[7],x+images[6]->getWidth(),y+height-images[7]->getHeight(),opacity);
g.fillRect(x+images[6]->getWidth(),y+height-images[7]->getHeight(),width-images[6]->getWidth()-images[8]->getWidth(),images[7]->getHeight());

g.setTiledImageFill(*images[3],x,y+images[0]->getHeight(),opacity);
g.fillRect(x,y+images[0]->getHeight(),images[3]->getWidth(),height-images[0]->getHeight()-images[6]->getHeight());

g.setTiledImageFill(*images[5],x+width-images[5]->getWidth(),y,opacity);
g.fillRect(x+width-images[5]->getWidth(),y+images[2]->getHeight(),images[5]->getWidth(),height-images[2]->getHeight()-images[8]->getHeight());

g.setTiledImageFill(*images[0],x,y,opacity);
g.fillRect(x,y,images[0]->getWidth(),images[0]->getHeight());

g.setTiledImageFill(*images[2],x+width-images[2]->getWidth(),y,opacity);
g.fillRect(x+width-images[2]->getWidth(),y,images[2]->getWidth(),images[2]->getHeight());

g.setTiledImageFill(*images[6],x,y+height-images[6]->getHeight(),opacity);
g.fillRect(x,y+height-images[6]->getHeight(),images[6]->getWidth(),images[6]->getHeight());

g.setTiledImageFill(*images[8],x+width-images[8]->getWidth(),y+height-images[8]->getHeight(),opacity);
g.fillRect(x+width-images[8]->getWidth(),y+height-images[8]->getHeight(),images[8]->getWidth(),images[8]->getHeight());

}

//-----------------------------------------------------------------------------------------------------------
NewLookAndFeel::NewLookAndFeel()
{
}

//-----------------------------------------------------------------------------------------------------------
NewLookAndFeel::~NewLookAndFeel()
{
setDefaultLookAndFeel (0);
}

juce_ImplementSingleton (NewLookAndFeel)[/code]


#5

Here I’m loading 2 images for a button background. The first is the normal state, the second is the clicked state. They are both in the same png file, that’s why I’m using the offset option.

Here’s the button declaration:

Here’s the code to load the png file:

[code]#define SkinPng(ID) dataPath + SkinSub + skinFolder + T("\Files\") + ID + T(".png")

Image* Button = ImageFileFormat::loadFrom(SkinPng(T(“Buttons”)));
newLookAndFeel->stripPinkImage(Button,newLookAndFeel->buttonBack[0],Button->getHeight()/2,0);
newLookAndFeel->stripPinkImage(Button,newLookAndFeel->buttonBack[1],Button->getHeight()/2,Button->getHeight()/2);
deleteAndZero(Button);
[/code]

And here’s how to draw a dinamic square, thanks to all this new functions. Here I’m drawing the alert box:

void NewLookAndFeel::fillResizableWindowBackground (Graphics& g, int w, int h, const BorderSize& border, ResizableWindow& window) { if (AlertBackground[0] == 0) LookAndFeel::fillResizableWindowBackground(g,w,h,border,window); else drawImageSquare(g,AlertBackground,0,0,w,h,1.0f); }

:mrgreen: 8)


#6

And here’s the topic that started it all…

http://www.rawmaterialsoftware.com/viewtopic.php?p=25658#p25658


#7

And here’s another example on how the pink lines determinate the 9 images:


#8

I also made some extra code for creating 3 image resizers and scroll-bar alternatives, including Vertically. I will post examples tomorrow, if people ask me to. :wink: