1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.graphics.Color;
14 
15 import java.lang.all;
16 
17 
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.internal.gtk.OS;
20 import org.eclipse.swt.graphics.Resource;
21 import org.eclipse.swt.graphics.RGB;
22 import org.eclipse.swt.graphics.Device;
23 
24 
25 
26 /**
27  * Instances of this class manage the operating system resources that
28  * implement SWT's RGB color model. To create a color you can either
29  * specify the individual color components as integers in the range
30  * 0 to 255 or provide an instance of an <code>RGB</code>.
31  * <p>
32  * Application code must explicitly invoke the <code>Color.dispose()</code>
33  * method to release the operating system resources managed by each instance
34  * when those instances are no longer required.
35  * </p>
36  *
37  * @see RGB
38  * @see Device#getSystemColor
39  * @see <a href="http://www.eclipse.org/swt/snippets/#color">Color and RGB snippets</a>
40  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: PaintExample</a>
41  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
42  */
43 public final class Color : Resource {
44     alias Resource.init_ init_;
45     /**
46      * the handle to the OS color resource
47      * (Warning: This field is platform dependent)
48      * <p>
49      * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
50      * public API. It is marked public only so that it can be shared
51      * within the packages provided by SWT. It is not available on all
52      * platforms and should never be accessed from application code.
53      * </p>
54      */
55     public GdkColor* handle;
56 
57 this(Device device) {
58     super(device);
59 }
60 
61 /**
62  * Constructs a new instance of this class given a device and the
63  * desired red, green and blue values expressed as ints in the range
64  * 0 to 255 (where 0 is black and 255 is full brightness). On limited
65  * color devices, the color instance created by this call may not have
66  * the same RGB values as the ones specified by the arguments. The
67  * RGB values on the returned instance will be the color values of
68  * the operating system color.
69  * <p>
70  * You must dispose the color when it is no longer required.
71  * </p>
72  *
73  * @param device the device on which to allocate the color
74  * @param red the amount of red in the color
75  * @param green the amount of green in the color
76  * @param blue the amount of blue in the color
77  *
78  * @exception IllegalArgumentException <ul>
79  *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
80  *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
81  * </ul>
82  *
83  * @see #dispose
84  */
85 public this(Device device, int red, int green, int blue) {
86     super(device);
87     init_(red, green, blue);
88     init_();
89 }
90 
91 /**
92  * Constructs a new instance of this class given a device and an
93  * <code>RGB</code> describing the desired red, green and blue values.
94  * On limited color devices, the color instance created by this call
95  * may not have the same RGB values as the ones specified by the
96  * argument. The RGB values on the returned instance will be the color
97  * values of the operating system color.
98  * <p>
99  * You must dispose the color when it is no longer required.
100  * </p>
101  *
102  * @param device the device on which to allocate the color
103  * @param rgb the RGB values of the desired color
104  *
105  * @exception IllegalArgumentException <ul>
106  *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
107  *    <li>ERROR_NULL_ARGUMENT - if the rgb argument is null</li>
108  *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue components of the argument are not between 0 and 255</li>
109  * </ul>
110  *
111  * @see #dispose
112  */
113 public this(Device device, in RGB rgb) {
114     super(device);
115     if (rgb is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
116     init_(rgb.red, rgb.green, rgb.blue);
117     init_();
118 }
119 
120 override
121 void destroy() {
122     int pixel = handle.pixel;
123     if (device.colorRefCount !is null) {
124         /* If this was the last reference, remove the color from the list */
125         if (--device.colorRefCount[pixel] is 0) {
126             device.gdkColors[pixel] = null;
127         }
128     }
129     auto colormap = OS.gdk_colormap_get_system();
130     OS.gdk_colormap_free_colors(colormap, handle, 1);
131     handle = null;
132 }
133 
134 /**
135  * Compares the argument to the receiver, and returns true
136  * if they represent the <em>same</em> object using a class
137  * specific comparison.
138  *
139  * @param object the object to compare with this object
140  * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
141  *
142  * @see #hashCode
143  */
144 public override equals_t opEquals(Object object) {
145     if (object is this) return true;
146     if ( auto color = cast(Color)object ){
147         GdkColor* gdkColor = color.handle;
148         if (handle is gdkColor) return true;
149         return device is color.device && handle.red is gdkColor.red &&
150             handle.green is gdkColor.green && handle.blue is gdkColor.blue;
151     }
152     return false;
153 }
154 
155 /**
156  * Returns the amount of blue in the color, from 0 to 255.
157  *
158  * @return the blue component of the color
159  *
160  * @exception SWTException <ul>
161  *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
162  * </ul>
163  */
164 public int getBlue() {
165     if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
166     return (handle.blue >> 8) & 0xFF;
167 }
168 
169 /**
170  * Returns the amount of green in the color, from 0 to 255.
171  *
172  * @return the green component of the color
173  *
174  * @exception SWTException <ul>
175  *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
176  * </ul>
177  */
178 public int getGreen() {
179     if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
180     return (handle.green >> 8) & 0xFF;
181 }
182 
183 /**
184  * Returns the amount of red in the color, from 0 to 255.
185  *
186  * @return the red component of the color
187  *
188  * @exception SWTException <ul>
189  *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
190  * </ul>
191  */
192 public int getRed() {
193     if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
194     return (handle.red >> 8) & 0xFF;
195 }
196 
197 /**
198  * Returns an integer hash code for the receiver. Any two
199  * objects that return <code>true</code> when passed to
200  * <code>equals</code> must return the same value for this
201  * method.
202  *
203  * @return the receiver's hash
204  *
205  * @see #equals
206  */
207 public override hash_t toHash() {
208     if (handle is null) return 0;
209     return handle.red ^ handle.green ^ handle.blue;
210 }
211 
212 /**
213  * Returns an <code>RGB</code> representing the receiver.
214  *
215  * @return the RGB for the color
216  *
217  * @exception SWTException <ul>
218  *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
219  * </ul>
220  */
221 public RGB getRGB () {
222     if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
223     return new RGB(getRed(), getGreen(), getBlue());
224 }
225 
226 /**
227  * Invokes platform specific functionality to allocate a new color.
228  * <p>
229  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
230  * API for <code>Color</code>. It is marked public only so that it
231  * can be shared within the packages provided by SWT. It is not
232  * available on all platforms, and should never be called from
233  * application code.
234  * </p>
235  *
236  * @param device the device on which to allocate the color
237  * @param handle the handle for the color
238  *
239  * @private
240  */
241 public static Color gtk_new(Device device, GdkColor* gdkColor) {
242     Color color = new Color(device);
243     color.handle = gdkColor;
244     return color;
245 }
246 
247 void init_(int red, int green, int blue) {
248     if ((red > 255) || (red < 0) ||
249         (green > 255) || (green < 0) ||
250         (blue > 255) || (blue < 0)) {
251             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
252     }
253     GdkColor* gdkColor = new GdkColor();
254     gdkColor.red = cast(short)((red & 0xFF) | ((red & 0xFF) << 8));
255     gdkColor.green = cast(short)((green & 0xFF) | ((green & 0xFF) << 8));
256     gdkColor.blue = cast(short)((blue & 0xFF) | ((blue & 0xFF) << 8));
257     auto colormap = OS.gdk_colormap_get_system();
258     if (!OS.gdk_colormap_alloc_color(colormap, gdkColor, true, true)) {
259         /* Allocate black. */
260         gdkColor = new GdkColor();
261         OS.gdk_colormap_alloc_color(colormap, gdkColor, true, true);
262     }
263     handle = gdkColor;
264     if (device.colorRefCount !is null) {
265         /* Make a copy of the color to put in the colors array */
266         GdkColor* colorCopy = new GdkColor();
267         colorCopy.red = handle.red;
268         colorCopy.green = handle.green;
269         colorCopy.blue = handle.blue;
270         colorCopy.pixel = handle.pixel;
271         device.gdkColors[colorCopy.pixel] = colorCopy;
272         device.colorRefCount[colorCopy.pixel]++;
273     }
274 }
275 
276 /**
277  * Returns <code>true</code> if the color has been disposed,
278  * and <code>false</code> otherwise.
279  * <p>
280  * This method gets the dispose state for the color.
281  * When a color has been disposed, it is an error to
282  * invoke any other method using the color.
283  *
284  * @return <code>true</code> when the color is disposed and <code>false</code> otherwise
285  */
286 public override bool isDisposed() {
287     return handle is null;
288 }
289 
290 /**
291  * Returns a string containing a concise, human-readable
292  * description of the receiver.
293  *
294  * @return a string representation of the receiver
295  */
296 public override String toString () {
297     if (isDisposed()) return "Color {*DISPOSED*}";
298     return Format( "Color {{{}, {}, {}}", getRed(), getGreen(), getBlue());
299 }
300 
301 }