Related
I am trying to draw a Rectangle Label with a text in it every tick.. I want a text to fit exactly in to a Rectangle_Label.. As a text i am using Label.. But cant get it to work exactly.. It is not correctly situated..
In Fact i would like to create a class that would do it all in one... Just like a rectangle with text in it that would be always having same co ordinance and size etc..
Any help would be greatly appreciated...
bool createRectangleLabel(long chart_ID,string name,string labelName,int shift,double price,string text,double xSize,double ySize,double xOffSet,double yOffSet,double xDistance,double yDistance)
{
if(ObjectCreate(chart_ID,labelName,OBJ_RECTANGLE_LABEL,0,TimeCurrent()-shift,price))
{
Print(xDistance+" "+yDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_BGCOLOR,clrBlack);
ObjectSetInteger(chart_ID,labelName,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YDISTANCE,yDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YSIZE,ySize);
ObjectSetInteger(chart_ID,labelName,OBJPROP_XSIZE,xSize);
ObjectSetString(chart_ID,labelName,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,ANCHOR_CENTER);
return true;
}
else
{
Print("createRectangleLabel return error code: ",GetLastError());
Print("+--------------------------------------------------------------+");
return false;
}
}
bool createLineText(long chart_ID,string name,string labelName,int shift,double price,string text)
{
int xDistance=0;
int yDistance=0;
int xSize,xOffSet;
int ySize,yOffSet;
bool i=ChartTimePriceToXY(chart_ID,0,TimeCurrent(),price,xDistance,yDistance);
if(ObjectCreate(chart_ID,name,OBJ_LABEL,0,TimeCurrent()-shift,price))
{
ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,clrWhite);
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,yDistance);
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,ANCHOR_CENTER);
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clrWhite);
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,10);
xSize = ObjectGet(name,OBJPROP_XSIZE);
ySize = ObjectGet(name,OBJPROP_YSIZE);
xOffSet = ObjectGet(name,OBJPROP_XOFFSET);
yOffSet = ObjectGet(name,OBJPROP_YOFFSET);
TextGetSize(name,xSize,ySize);
createRectangleLabel(chart_ID,name,labelName,shift,price,text,xSize,ySize,xOffSet,yOffSet,xDistance,yDistance);
return true;
}
else
{
Print("createLineText return error code: ",GetLastError());
Print("+--------------------------------------------------------------+");
return false;
}
}
You cannot call ObjectCreate() every tick - it would return an error 4200.
If you check the object exists before creating, that would help. Alternative approach would be to try to create the object and assign it with some necessary properties (e.g., color of the object, anchor etc) in one block, and move it in another.
if(ObjectFind(chart_id,labelName)<0){
if(ObjectCreate(chart_ID,labelName,OBJ_RECTANGLE_LABEL,0,TimeCurrent()-shift,price)){
ObjectSetInteger(chart_ID,labelName,OBJPROP_BGCOLOR,clrBlack);//etc.
}
ObjectSetInteger(chart_ID,labelName,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YDISTANCE,yDistance);//if you need to move the object or take other steps each tick, e.g. update text - do it here
}
You're thinking along the right lines when you say that you'd like to create a class. Fortunately for you, the standard library already includes all the classes you need to make chart objects. Documentation
Example Indicator:
#property strict
#property indicator_chart_window
#include <ChartObjects\ChartObjectsTxtControls.mqh>
class MyRectLabel : public CChartObjectRectLabel
{
CChartObjectLabel m_label;
public:
bool Create(long chart, const string name, const int window,
const int X, const int Y, const int sizeX, const int sizeY)
{
if(!CChartObjectRectLabel::Create(chart,name,window,X,Y,sizeX,sizeY))
return false;
return m_label.Create(chart, name + "_", window, X + 8, Y + 12);
}
bool Color(const color clr){
return m_label.Color(clr);
}
bool Description(const string text){
return m_label.Description(text);
}
bool FontSize(const int size){
return m_label.FontSize(size);
}
bool ToolTip(const string text){
return (this.ToolTip(text) && m_label.Tooltip(text));
}
};
//+------------------------------------------------------------------+
MyRectLabel rect_label;
//+------------------------------------------------------------------+
int OnInit()
{
if(!rect_label.Create(0, "rlabel", 0, 5, 25, 100, 50)
|| !rect_label.BackColor(clrWhiteSmoke)
|| !rect_label.Description("LABEL!")
|| !rect_label.Tooltip("I am a rectangle label")
|| !rect_label.Color(clrBlack)
|| !rect_label.FontSize(18)
)
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int start()
{
static double last_price = 0.;
rect_label.Description(DoubleToString(Bid, _Digits));
if(Bid > last_price)
rect_label.Color(clrLimeGreen);
else
rect_label.Color(clrRed);
last_price = Bid;
return 0;
}
I am using RajawaliVR library.
I have added a plane and applied texture to it. Know I want to know when my object is being looked at so that I can trigger some even. Is there anything in RajawaliVR or google cardboad that can help me achieve this.
Material cruiserMaterial = new Material();
cruiserMaterial.setDiffuseMethod(new DiffuseMethod.Lambert());
cruiserMaterial.setColorInfluence(0);
cruiserMaterial.enableLighting(true);
try {
cruiserMaterial.addTexture(new Texture("spaceCruiserTex",
R.drawable.image2));
} catch (TextureException e) {
e.printStackTrace();
}
Object3D leftPlane = new Plane(10f, 10f, 1, 1, 1);
leftPlane.setMaterial(cruiserMaterial);
leftPlane.setRotZ(90);
Object3D container = new Object3D();
container.addChild(leftPlane);
container.setRotX(90);
container.setRotY(90);
container.setRotZ(90);
container.setZ(-20);
getCurrentScene().addChild(container);
Just put this in your renderers main loop (OnDrawFrame), iterate a list with objects and pass the object as parameter. The method will return true if you are currently looking at an object.
private static final float YAW_LIMIT = 0.12f;
private static final float PITCH_LIMIT = 0.12f;
/**
* Check if user is looking at object by calculating where the object is in eye-space.
*
* #return true if the user is looking at the object.
*/
private boolean isLookingAtObject(WorldObject object) {
float[] initVec = { 0, 0, 0, 1.0f };
float[] objPositionVec = new float[4];
// Convert object space to camera space. Use the headView from onNewFrame.
Matrix.multiplyMM(mModelView, 0, this.getHeadViewMatrix(), 0, object.getModel().getModelMatrix().getFloatValues(), 0);
Matrix.multiplyMV(objPositionVec, 0, mModelView, 0, initVec, 0);
float pitch = (float) Math.atan2(objPositionVec[1], -objPositionVec[2]);
float yaw = (float) Math.atan2(objPositionVec[0], -objPositionVec[2]);
return Math.abs(pitch) < PITCH_LIMIT && Math.abs(yaw) < YAW_LIMIT;
}
So I have the following code:
public class Minesweeper extends MIDlet implements CommandListener {
public static String error = "";
public void startApp() throws MIDletStateChangeException {
Display display = Display.getDisplay(this);
canvas = new MCanvas();
canvas.addCommand(exitCommand);
canvas.addCommand(okCommand);
canvas.addCommand(newCommand);
canvas.setCommandListener(this);
try{
display.setCurrent(canvas);
} catch (Exception e) {
error = e.toString();
}
}
}
When I leave display.setCurrent(canvas); outside of the try block, the app fails with a NullPointerException. When I comment out that line, the app works (although obviously no canvas is added). So the error is caused by that line, or something that that line causes.
So I suround that line with try/catch. Although the error is caused by that line, the error still happens when the line is surrounded by try/catch. How can I catch the error? (I've tried this using Throwable as well, and it is still not caught.
MCanvas:
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
public class MCanvas extends Canvas {
protected void paint(Graphics g){
//Minesweeper.p("repaint");
Space[] data = Minesweeper.topaint;
for(int x=0; x<data.length; x++){
data[x].print();
int r = data[x].row * 10;
int c = data[x].col * 10;
int v = data[x].value;
String s = "";
//System.out.println("r:"+Integer.toString(r)+" c:"+Integer.toString(c)+" s:"+Integer.toString(v));
g.setColor(250, 0, 0);
//Minesweeper.p("if");
if(data[x].open){
switch(v){
case 0:
g.setColor(50, 50, 50);
break;
case 1:
g.setColor(100, 50, 50);
s = "1";
break;
case 2:
g.setColor(150, 50, 50);
s = "2";
break;
case 3:
g.setColor(200, 50, 50);
s = "3";
break;
case 4:
g.setColor(250, 50, 50);
s = "4";
break;
case 5:
g.setColor(250, 100, 100);
s = "5";
break;
case 6:
g.setColor(250, 125, 125);
s = "6";
break;
case 7:
g.setColor(250, 150, 150);
s = "7";
break;
case 8:
g.setColor(250, 175, 175);
s = "8";
break;
case 9:
g.setColor(250, 200, 200);
break;
default:
g.setColor(250, 100, 100);
}
} else {
g.setColor(0,0,0);
}
g.fillRect(c, r, 10, 10);
g.setColor(250, 250, 250);
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
g.setFont(font);
g.drawString(s, c+5, r+8, Graphics.HCENTER | Graphics.BASELINE);
if(data[x].hover){
g.setColor(250, 250, 250);
g.drawLine(c, r, c, r+9);
g.drawLine(c, r, c+9, r);
g.drawLine(c+9, r, c+9, r+9);
g.drawLine(c, r+9, c+9, r+9);
}
//Minesweeper.p("here?");
}
//Minesweeper.p("here");
//Minesweeper.p(Minesweeper.error);
if(Minesweeper.error != null){
g.drawString(Minesweeper.error, 10, 10, Graphics.HCENTER | Graphics.BASELINE);
}
Minesweeper.p("msg:"+Minesweeper.message);
g.setColor(0, 0, 0);
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE);
g.setFont(font);
g.drawString(Minesweeper.message, this.getWidth()/2, this.getHeight()-10, Graphics.HCENTER | Graphics.BASELINE);
Font fontsm = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
g.setFont(fontsm);
}
protected void keyPressed(int keyCode) {
int gameaction = getGameAction(keyCode);
int c = Minesweeper.selected.col;
int r = Minesweeper.selected.row;
switch (gameaction) {
case UP:
Minesweeper.p("UP");
if(r>0){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row - 1, Minesweeper.selected.col).gohere();
}
break;
case DOWN:
Minesweeper.p("DOWN");
if(r<Minesweeper.height-1){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row + 1, Minesweeper.selected.col).gohere();
}
break;
case LEFT:
Minesweeper.p("LEFT");
if(c>0){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col - 1).gohere();
}
break;
case RIGHT:
Minesweeper.p("RIGHT");
if(c<Minesweeper.length-1){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col + 1).gohere();
}
break;
}
repaint();
}
}
As explained in Display.setCurrent API javadocs,
...The setCurrent() method returns immediately, without waiting for the change to take place...
Because of above, exceptions that may occur in calls triggered by setCurrent may (and most likely will) slip through your try-catch.
To be able to catch and report such exceptions, one should study what calls are triggered by setCurrent (in your case, these are explained in API javadocs for Canvas, Event Delivery section), cover these by try-catch blocks where appropriate and design the appropriate way to report exceptions if these occur.
In your case, try-catch could likely surround code in MCanvas.paint (this is where NPE likely occurs) and exceptions could be reported for example by showing appropriate screen with error message (eg Alert) by invoking setCurrent for that screen from catch block.
If I were you I would continue to insert try/catch blocks in the MCanvas class.
It is difficult for anyone to figure out where your NullPointerException occurs without seeing more of the code.
The only question I can come up with, from the code you pasted so far, is:
Does your Minesweeper class contain a static array of object Space called topaint? Did you declare it but maybe forgot to fill it with data?
Space[] topaint = new Space[20]; // Declared, but nothing in it yet.
Trying to access Minesweeper.topaint[0] will give a NullPointerException, unless you also do
topaint[0] = new Space();
I've got a MonoTouch app that does an HTTP POST with a 3.5MB file, and it is very unstable on the primary platforms that I test on (iPhone 3G with OS 3.1.2 and iPhone 4 with OS 4.2.1). I'll describe what I'm doing here and maybe someone can tell me if I'm doing something wrong.
In order to rule out the rest of my app, I've whittled this down to a tiny sample app. The app is an iPhone OpenGL Project and it does only this:
At startup, allocate 6MB of memory in 30k chunks. This simulates my app's memory usage.
Read a 3.5MB file into memory.
Create a thread to post the data. (Make a WebRequest object, use GetRequestStream(), and write the 3.5MB data in).
When the main thread detects that the posting thread is done, goto step 2 and repeat.
Also, each frame, I allocate 0-100k to simulate the app doing something. I don't keep any references to this data so it should be getting garbage collected.
iPhone 3G Result: The app gets through 6 to 8 uploads and then the OS kills it. There is no crash log, but there is a LowMemory log showing that the app was jettisoned.
iPhone 4 Result: It gets an Mprotect error around the 11th upload.
A few data points:
Instruments does NOT show the memory increasing as the app continues to upload.
Instruments doesn't show any significant leaks (maybe 1 kilobyte total).
It doesn't matter whether I write the post data in 64k chunks or all at once with one Stream.Write() call.
It doesn't matter whether I wait for a response (HttpWebRequest.HaveResponse) or not before starting the next upload.
It doesn't matter if the POST data is even valid. I've tried using valid POST data and I've tried sending 3MB of zeros.
If the app is not allocating any data each frame, then it takes longer to run out of memory (but as mentioned before, the memory that I'm allocating each frame is not referenced after the frame it was allocated on, so it should be scooped up by the GC).
If nobody has any ideas, I'll file a bug with Novell, but I wanted to see if I'm doing something wrong here first.
If anyone wants the full sample app, I can provide it, but I've pasted the contents of my EAGLView.cs below.
using System;
using System.Net;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using OpenTK.Platform.iPhoneOS;
using MonoTouch.CoreAnimation;
using OpenTK;
using OpenTK.Graphics.ES11;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
using MonoTouch.OpenGLES;
namespace CrashTest
{
public partial class EAGLView : iPhoneOSGameView
{
[Export("layerClass")]
static Class LayerClass ()
{
return iPhoneOSGameView.GetLayerClass ();
}
[Export("initWithCoder:")]
public EAGLView (NSCoder coder) : base(coder)
{
LayerRetainsBacking = false;
LayerColorFormat = EAGLColorFormat.RGBA8;
ContextRenderingApi = EAGLRenderingAPI.OpenGLES1;
}
protected override void ConfigureLayer (CAEAGLLayer eaglLayer)
{
eaglLayer.Opaque = true;
}
protected override void OnRenderFrame (FrameEventArgs e)
{
SimulateAppAllocations();
UpdatePost();
base.OnRenderFrame (e);
float[] squareVertices = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
byte[] squareColors = { 255, 255, 0, 255, 0, 255, 255, 255, 0, 0,
0, 0, 255, 0, 255, 255 };
MakeCurrent ();
GL.Viewport (0, 0, Size.Width, Size.Height);
GL.MatrixMode (All.Projection);
GL.LoadIdentity ();
GL.Ortho (-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
GL.MatrixMode (All.Modelview);
GL.Rotate (3.0f, 0.0f, 0.0f, 1.0f);
GL.ClearColor (0.5f, 0.5f, 0.5f, 1.0f);
GL.Clear ((uint)All.ColorBufferBit);
GL.VertexPointer (2, All.Float, 0, squareVertices);
GL.EnableClientState (All.VertexArray);
GL.ColorPointer (4, All.UnsignedByte, 0, squareColors);
GL.EnableClientState (All.ColorArray);
GL.DrawArrays (All.TriangleStrip, 0, 4);
SwapBuffers ();
}
AsyncHttpPost m_Post;
int m_nPosts = 1;
byte[] LoadPostData()
{
// Just return 3MB of zeros. It doesn't matter whether this is valid POST data or not.
return new byte[1024 * 1024 * 3];
}
void UpdatePost()
{
if ( m_Post == null || m_Post.PostStatus != AsyncHttpPostStatus.InProgress )
{
System.Console.WriteLine( string.Format( "Starting post {0}", m_nPosts++ ) );
byte [] postData = LoadPostData();
m_Post = new AsyncHttpPost(
"https://api-video.facebook.com/restserver.php",
"multipart/form-data; boundary=" + "8cdbcdf18ab6640",
postData );
}
}
Random m_Random = new Random(0);
List< byte [] > m_Allocations;
List< byte[] > m_InitialAllocations;
void SimulateAppAllocations()
{
// First time through, allocate a bunch of data that the app would allocate.
if ( m_InitialAllocations == null )
{
m_InitialAllocations = new List<byte[]>();
int nInitialBytes = 6 * 1024 * 1024;
int nBlockSize = 30000;
for ( int nCurBytes = 0; nCurBytes < nInitialBytes; nCurBytes += nBlockSize )
{
m_InitialAllocations.Add( new byte[nBlockSize] );
}
}
m_Allocations = new List<byte[]>();
for ( int i=0; i < 10; i++ )
{
int nAllocationSize = m_Random.Next( 10000 ) + 10;
m_Allocations.Add( new byte[nAllocationSize] );
}
}
}
public enum AsyncHttpPostStatus
{
InProgress,
Success,
Fail
}
public class AsyncHttpPost
{
public AsyncHttpPost( string sURL, string sContentType, byte [] postData )
{
m_PostData = postData;
m_PostStatus = AsyncHttpPostStatus.InProgress;
m_sContentType = sContentType;
m_sURL = sURL;
//UploadThread();
m_UploadThread = new Thread( new ThreadStart( UploadThread ) );
m_UploadThread.Start();
}
void UploadThread()
{
using ( MonoTouch.Foundation.NSAutoreleasePool pool = new MonoTouch.Foundation.NSAutoreleasePool() )
{
try
{
HttpWebRequest request = WebRequest.Create( m_sURL ) as HttpWebRequest;
request.Method = "POST";
request.ContentType = m_sContentType;
request.ContentLength = m_PostData.Length;
// Write the post data.
using ( Stream stream = request.GetRequestStream() )
{
stream.Write( m_PostData, 0, m_PostData.Length );
stream.Close();
}
System.Console.WriteLine( "Finished!" );
// We're done with the data now. Let it be garbage collected.
m_PostData = null;
// Finished!
m_PostStatus = AsyncHttpPostStatus.Success;
}
catch ( System.Exception e )
{
System.Console.WriteLine( "Error in AsyncHttpPost.UploadThread:\n" + e.Message );
m_PostStatus = AsyncHttpPostStatus.Fail;
}
}
}
public AsyncHttpPostStatus PostStatus
{
get
{
return m_PostStatus;
}
}
Thread m_UploadThread;
// Queued to be handled in the main thread.
byte [] m_PostData;
AsyncHttpPostStatus m_PostStatus;
string m_sContentType;
string m_sURL;
}
}
I think you should read in your file 1 KB (or some arbitrary size) at a time and write it to the web request.
Code similar to this:
byte[] buffer = new buffer[1024];
int bytesRead = 0;
using (FileStream fileStream = File.OpenRead("YourFile.txt"))
{
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
httpPostStream.Write(buffer, 0, bytesRead);
}
}
This is off the top of my head, but I think it's right.
This way you don't have an extra 3MB floating around in memory when you don't really need to. I think tricks like this are even more important on iDevices (or other devices) than on the desktop.
Test the buffer size too, a larger buffer will get you better speeds up to a point (I remember 8KB being pretty good).
I'm trying to write a simple property grid to allow the users to modify the colours of a Chart. By default, a Chart has a "Palette" property, which is of the enumeration type "ChartColorPalette". If the object which underlies my property grid also has a "Palette" property of the same type, I get the drop-down list of possible values. What I don't get however, is the little stripey images to the left of the value names.
Now, I can write a UITypeEditor derived class and have the "PaintValue" draw little resource bitmaps which I have culled from the screen using "Paint" or somesuch, but this seems rather tedious.
Does anyone know if there is already a type editor for the "ChartColorPalette" enumeration which I can use to get the little bitmaps ?
as it happens, writing the UITypeEditor is not that tricky, and not that much code either.
Firstly I created a type editor that looked like this:
private class ChartColorPaletteEditor : UITypeEditor
{
public override bool GetPaintValueSupported(ITypeDescriptorContext context)
{
return true;
}
public override void PaintValue(PaintValueEventArgs e)
{
String paletteName = e.Value.ToString();
String baseName = this.GetType().Namespace + ".MyChart";
ResourceManager mgr = new ResourceManager(baseName, this.GetType().Assembly);
Bitmap bmp = mgr.GetObject(paletteName) as Bitmap;
if (bmp != null)
{
e.Graphics.DrawImage(bmp, e.Bounds);
bmp.Dispose();
}
}
}
I attached this to my control property in the usual way:
[DefaultValue(typeof(ChartColorPalette), "BrightPastel")]
[Editor(typeof(ChartColorPaletteEditor), typeof(System.Drawing.Design.UITypeEditor))]
[Category("Appearance")]
[Description("The named palette to use when choosing the colour scheme for the chart series lines.")]
public ChartColorPalette Palette { get; set; }
Then I added a small PNG resource for each of the little palette images. I had a derived control "MyChart" which inherited from "Chart" and I added the images to that as resources (making sure to set the "Persistance" property to "Embedded in .resx" to save having to keep the PNG files about). The names of the PNG files matched the names in the ChartColorPalette enumeration.
The only issue was where to get the little 20 x 14 images from. I originally just culled them using Paint.exe but didn't like that, so I wrote some code to generate them for me. That was fairly simple, once I had found the colour values that are used by the Charting control. One subtlety is that, where there are more than 12 colours in a palette, the little bitmap uses every other colour. That code looked like this:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Windows.Forms.DataVisualization.Charting;
namespace ConsoleApplication10
{
class Program
{
static void Main(string[] args)
{
Enum.GetValues(typeof(ChartColorPalette)).OfType<ChartColorPalette>().ToList().ForEach(GeneratePNG);
}
static void GeneratePNG(ChartColorPalette palette)
{
if (palette == ChartColorPalette.None) return;
Color[] colours = palette.GetColors();
if (colours.Length >= 12)
{
colours = new Color[] { colours[0], colours[2], colours[4], colours[6], colours[8], colours[10] };
}
else
{
colours = new Color[] { colours[0], colours[1], colours[2], colours[3], colours[4], colours[5] };
}
using (Bitmap bmp = new Bitmap(20, 14))
{
using (Graphics gr = Graphics.FromImage(bmp))
{
using (SolidBrush b1 = new SolidBrush(colours[0]),
b2 = new SolidBrush(colours[1]),
b3 = new SolidBrush(colours[2]),
b4 = new SolidBrush(colours[3]),
b5 = new SolidBrush(colours[4]),
b6 = new SolidBrush(colours[5]))
{
int height = bmp.Height - 2;
gr.DrawRectangle(Pens.Black, 0, 0, bmp.Width - 1, bmp.Height - 1);
gr.FillRectangle(b1, new Rectangle(1, 1, 3, height));
gr.FillRectangle(b2, new Rectangle(4, 1, 3, height));
gr.FillRectangle(b3, new Rectangle(7, 1, 3, height));
gr.FillRectangle(b4, new Rectangle(10, 1, 3, height));
gr.FillRectangle(b5, new Rectangle(13, 1, 3, height));
gr.FillRectangle(b6, new Rectangle(16, 1, 3, height));
}
}
String path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
path = Path.Combine(path, #"Visual Studio 2010\Projects\DataVisualization.Charting\Palette Bitmaps");
String filename = palette.ToString() + ".png";
bmp.Save(Path.Combine(path, filename), ImageFormat.Png);
}
}
}
public static class Extensions
{
public static Color[] GetColors(this ChartColorPalette value)
{
switch (value)
{
case ChartColorPalette.Berry:
return GetColors(0x8a2be2, 0xba55d3, 0x4169e1, 0xc71585, 0x0000ff, 0x8a2be2, 0xda70d6, 0x7b68ee, 0xc000c0, 0x0000cd, 0x800080);
case ChartColorPalette.Bright:
return GetColors(0x008000, 0x0000ff, 0x800080, 0x00ff00, 0xff00ff, 0x008080, 0xffff00, 0x808080, 0x00ffff, 0x000080, 0x800000, 0xff0000, 0x808000, 0xc0c0c0, 0xff6347, 0xffe4b5);
case ChartColorPalette.BrightPastel:
return GetColors(0x418cf0, 0xfcb441, 0xe0400a, 0x056492, 0xbfbfbf, 0x1a3b69, 0xffe382, 0x129cdd, 0xca6b4b, 0x005cdb, 0xf3d288, 0x506381, 0xf1b9a8, 0xe0830a, 0x7893be);
case ChartColorPalette.Chocolate:
return GetColors(0xa0522d, 0xd2691e, 0x8b0000, 0xcd853f, 0xa52a2a, 0xf4a460, 0x8b4513, 0xc04000, 0xb22222, 0xb65c3a);
case ChartColorPalette.EarthTones:
return GetColors(0xff8000, 0xb8860b, 0xc04000, 0x6b8e23, 0xcd853f, 0xc0c000, 0x228b22, 0xd2691e, 0x808000, 0x20b2aa, 0xf4a460, 0x00c000, 0x8fbc8b, 0xb22222, 0x8b4513, 0xc00000);
case ChartColorPalette.Excel:
return GetColors(0x9999ff, 0x993366, 0xffffcc, 0xccffff, 0x660066, 0xff8080, 0x0066cc, 0xccccff, 0x000080, 0xff00ff, 0xffff00, 0x00ffff, 0x800080, 0x800000, 0x008080, 0x0000ff);
case ChartColorPalette.Fire:
return GetColors(0xffd700, 0xff0000, 0xff1493, 0xdc143c, 0xff8c00, 0xff00ff, 0xffff00, 0xff4500, 0xc71585, 0xdde221);
case ChartColorPalette.Grayscale:
return GetColors(0xc8c8c8, 0xbdbdbd, 0xb2b2b2, 0xa7a7a7, 0x9c9c9c, 0x919191, 0x868686, 0x7b7b7b, 0x707070, 0x656565, 0x5a5a5a, 0x4f4f4f, 0x444444, 0x393939, 0x2e2e2e, 0x232323);
case ChartColorPalette.Light:
return GetColors(0xe6e6fa, 0xfff0f5, 0xffdab9, 0xfffacd, 0xffe4e1, 0xf0fff0, 0xf0f8ff, 0xf5f5f5, 0xfaebd7, 0xe0ffff);
case ChartColorPalette.Pastel:
return GetColors(0x87ceeb, 0x32cd32, 0xba55d3, 0xf08080, 0x4682b4, 0x9acd32, 0x40e0d0, 0xff69b4, 0xf0e68c, 0xd2b48c, 0x8fbc8b, 0x6495ed, 0xdda0dd, 0x5f9ea0, 0xffdab9, 0xffa07a);
case ChartColorPalette.SeaGreen:
return GetColors(0x2e8b57, 0x66cdaa, 0x4682b4, 0x008b8b, 0x5f9ea0, 0x3cb371, 0x48d1cc, 0xb0c4de, 0xffffff, 0x87ceeb);
case ChartColorPalette.SemiTransparent:
return GetColors(0xff6969, 0x69ff69, 0x6969ff, 0xffff69, 0x69ffff, 0xff69ff, 0xcdb075, 0xffafaf, 0xafffaf, 0xafafff, 0xffffaf, 0xafffff, 0xffafff, 0xe4d5b5, 0xa4b086, 0x819ec1);
case ChartColorPalette.None:
default:
return GetColors(0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000);
}
}
private static Color[] GetColors(params Int32[] values)
{
return values.Select(value => Color.FromArgb(255, Color.FromArgb(value))).ToArray(); // alpha channel of 255 for fully opaque
}
}
}
Hope this is useful to someone out there...