1 /********************************************************************************
2 * *
3 * C h a r t B a s e W i d g e t *
4 * *
5 *********************************************************************************
6 * Copyright (C) 2003,2005 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
21 *********************************************************************************
22 * $Id: FXChart.cpp,v 1.15 2005/01/16 16:06:06 fox Exp $ *
23 ********************************************************************************/
24 #include "fx.h"
25 #ifdef HAVE_PNG_H
26 #include "FXPNGImage.h"
27 #endif
28 #ifdef HAVE_JPEG_H
29 #include "FXJPGImage.h"
30 #endif
31 #ifdef HAVE_TIFF_H
32 #include "FXTIFImage.h"
33 #endif
34 #include "FXChart.h"
35
36 /*
37 Notes:
38 */
39
40
41 using namespace FX;
42
43
44 /*******************************************************************************/
45
46 namespace FX {
47
48 // Map
49 FXDEFMAP(FXChart) FXChartMap[]={
50 FXMAPFUNC(SEL_PAINT,0,FXChart::onPaint),
51 FXMAPFUNC(SEL_CLIPBOARD_LOST,0,FXChart::onClipboardLost),
52 FXMAPFUNC(SEL_CLIPBOARD_REQUEST,0,FXChart::onClipboardRequest),
53 FXMAPFUNC(SEL_QUERY_TIP,0,FXChart::onQueryTip),
54 FXMAPFUNC(SEL_QUERY_HELP,0,FXChart::onQueryHelp),
55 };
56
57
58 // Object implementation
59 FXIMPLEMENT(FXChart,FXComposite,FXChartMap,ARRAYNUMBER(FXChartMap))
60
61
62 /*******************************************************************************/
63
64 // Drag type names
65 const FXchar FXChart::bmpTypeName[]="image/x-bmp";
66 const FXchar FXChart::gifTypeName[]="image/gif";
67 const FXchar FXChart::jpgTypeName[]="image/jpeg";
68 const FXchar FXChart::pngTypeName[]="image/png";
69 const FXchar FXChart::csvTypeName[]="Csv";
70 const FXchar FXChart::tifTypeName[]="image/tiff";
71
72 // Drag types
73 FXDragType FXChart::bmpType=0;
74 FXDragType FXChart::gifType=0;
75 FXDragType FXChart::jpgType=0;
76 FXDragType FXChart::pngType=0;
77 FXDragType FXChart::csvType=0;
78 FXDragType FXChart::tifType=0;
79
80
81 /*******************************************************************************/
82
83 // Init
FXChart()84 FXChart::FXChart(){
85 flags|=FLAG_SHOWN|FLAG_ENABLED|FLAG_DROPTARGET;
86 }
87
88
89 // Make a chart
FXChart(FXComposite * p,FXObject * tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h)90 FXChart::FXChart(FXComposite* p,FXObject* tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h):
91 FXComposite(p,opts,x,y,w,h){
92 chart=new FXImage(getApp(),NULL,IMAGE_DITHER|IMAGE_SHMI|IMAGE_SHMP,w,h);
93 flags|=FLAG_SHOWN|FLAG_ENABLED|FLAG_DROPTARGET;
94 target=tgt;
95 message=sel;
96 fill.style=FILLSTYLE_SOLID;
97 fill.hatch=STIPPLE_NONE;
98 fill.image=NULL;
99 fill.color=FXRGB(103,103,255);
100 fill.backcolor=0;
101 fill.lower=FXRGB(255,255,255);
102 fill.upper=FXRGB(0,0,255);
103 }
104
105
106 // Create window; register drag types
create()107 void FXChart::create(){
108 FXComposite::create();
109 chart->create();
110 if(fill.image) fill.image->create();
111 if(!colorType) colorType=getApp()->registerDragType(colorTypeName);
112 if(!textType) textType=getApp()->registerDragType(textTypeName);
113 if(!bmpType) bmpType=getApp()->registerDragType(bmpTypeName);
114 if(!gifType) gifType=getApp()->registerDragType(gifTypeName);
115 if(!jpgType) jpgType=getApp()->registerDragType(jpgTypeName);
116 if(!pngType) pngType=getApp()->registerDragType(pngTypeName);
117 if(!csvType) csvType=getApp()->registerDragType(csvTypeName);
118 if(!tifType) tifType=getApp()->registerDragType(tifTypeName);
119 }
120
121
122 // Detach window; zero out drag types
detach()123 void FXChart::detach(){
124 FXComposite::detach();
125 chart->detach();
126 textType=0;
127 colorType=0;
128 bmpType=0;
129 gifType=0;
130 jpgType=0;
131 pngType=0;
132 csvType=0;
133 tifType=0;
134 }
135
136
137 #define MAXSTEPS 128
138
139 // Resize the dial
layout()140 void FXChart::layout(){
141 register FXint rr,gg,bb,dr,dg,db,r1,g1,b1,r2,g2,b2,xl,xr,n,t,xx,dx;
142
143 // Do regular layout of child widgets
144 FXComposite::layout();
145
146 // Resize off-screen buffer if needed
147 if(chart->getWidth()!=width || chart->getHeight()!=height){
148 chart->resize(width,height);
149 FXTRACE((1,"new size = %d x %d\n",width,height));
150 }
151
152 // FIXME regenerate plot
153 FXDCWindow dc(chart);
154 switch(fill.style){
155 case FILLSTYLE_SOLID:
156 dc.setStipple(STIPPLE_NONE);
157 dc.setFillStyle(FILL_SOLID);
158 dc.setForeground(fill.color);
159 dc.fillRectangle(0,0,width,height);
160 break;
161 case FILLSTYLE_HATCH:
162 if(fill.backcolor){
163 dc.setFillStyle(FILL_OPAQUESTIPPLED);
164 dc.setBackground(fill.backcolor);
165 }
166 else{
167 dc.setFillStyle(FILL_STIPPLED);
168 }
169 dc.setStipple((FXStipplePattern)fill.hatch);
170 dc.setForeground(fill.color);
171 dc.fillRectangle(0,0,width,height);
172 break;
173 case FILLSTYLE_TEXTURE:
174 dc.setStipple(STIPPLE_NONE);
175 dc.setFillStyle(FILL_TILED);
176 dc.setTile(fill.image);
177 dc.fillRectangle(0,0,width,height);
178 break;
179 case FILLSTYLE_IMAGE:
180 dc.setStipple(STIPPLE_NONE);
181 dc.setFillStyle(FILL_TILED);
182 dc.setTile(fill.image);
183 dc.fillRectangle(0,0,width,height);
184 break;
185 case FILLSTYLE_HORIZONTAL:
186 dc.setStipple(STIPPLE_NONE);
187 dc.setFillStyle(FILL_SOLID);
188 dc.setForeground(FXRGB(255,0,255));
189 dc.fillRectangle(0,0,width,height);
190
191 r1=FXREDVAL(fill.lower); r2=FXREDVAL(fill.upper); dr=r2-r1;
192 g1=FXGREENVAL(fill.lower); g2=FXGREENVAL(fill.upper); dg=g2-g1;
193 b1=FXBLUEVAL(fill.lower); b2=FXBLUEVAL(fill.upper); db=b2-b1;
194
195 n=FXABS(dr);
196 if((t=FXABS(dg))>n) n=t;
197 if((t=FXABS(db))>n) n=t;
198 FXTRACE((1,"max(|dr|,|dg|,|db|)=%d \n",n));
199 n++;
200 if(n>width) n=width;
201 if(n>MAXSTEPS) n=MAXSTEPS;
202 FXTRACE((1,"n=%d \n",n));
203
204 rr=(r1<<16)+32767;
205 gg=(g1<<16)+32767;
206 bb=(b1<<16)+32767;
207 xx=32767;
208
209 dr=(dr<<16)/n;
210 dg=(dg<<16)/n;
211 db=(db<<16)/n;
212 dx=(width<<16)/n;
213
214 do{
215 xl=xx>>16;
216 xx+=dx;
217 xr=xx>>16;
218 dc.setForeground(FXRGB(rr>>16,gg>>16,bb>>16));
219 dc.fillRectangle(xl,0,xr-xl,height);
220 FXTRACE((1,"fillRectangle(%d,%d,%d,%d) width=%d n=%d\n",xl,0,xr-xl,height,width,n));
221 rr+=dr;
222 gg+=dg;
223 bb+=db;
224 }
225 while(xr<width);
226
227 break;
228 case FILLSTYLE_VERTICAL:
229 break;
230 case FILLSTYLE_DIAGONAL:
231 break;
232 case FILLSTYLE_RDIAGONAL:
233 break;
234 }
235 flags&=~FLAG_DIRTY;
236 }
237
238
239 // We were asked about tip text
onQueryTip(FXObject * sender,FXSelector sel,void * ptr)240 long FXChart::onQueryTip(FXObject* sender,FXSelector sel,void* ptr){
241 if(FXWindow::onQueryTip(sender,sel,ptr)) return 1;
242 if((flags&FLAG_TIP) && !tip.empty()){
243 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&tip);
244 return 1;
245 }
246 return 0;
247 }
248
249
250 // We were asked about status text
onQueryHelp(FXObject * sender,FXSelector sel,void * ptr)251 long FXChart::onQueryHelp(FXObject* sender,FXSelector sel,void* ptr){
252 if(FXWindow::onQueryHelp(sender,sel,ptr)) return 1;
253 if((flags&FLAG_HELP) && !help.empty()){
254 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&help);
255 return 1;
256 }
257 return 0;
258 }
259
260
261 // Lost clipboard, so destroy data
onClipboardLost(FXObject *,FXSelector,void *)262 long FXChart::onClipboardLost(FXObject*,FXSelector,void*){
263 return 1;
264 }
265
266
267 // Request for clipboard data
onClipboardRequest(FXObject * sender,FXSelector sel,void * ptr)268 long FXChart::onClipboardRequest(FXObject *sender,FXSelector sel,void *ptr){
269 FXEvent *event=(FXEvent*)ptr;
270 unsigned long size;
271 FXuchar *data;
272
273 // Try handling it in base class first
274 if(FXComposite::onClipboardRequest(sender,sel,ptr)) return 1;
275
276 // One of the supported image types?
277 if(event->target==bmpType || event->target==gifType || event->target==jpgType || event->target==pngType || event->target==imageType){
278 FXMemoryStream ms;
279
280 // Read back pixels
281 chart->restore();
282
283 // Open memory stream
284 ms.open(FXStreamSave,NULL);
285
286 // Render image to memory stream
287 if(event->target==bmpType)
288 fxsaveBMP(ms,chart->getData(),chart->getWidth(),chart->getHeight());
289 else if(event->target==gifType)
290 fxsaveGIF(ms,chart->getData(),chart->getWidth(),chart->getHeight());
291 #ifdef HAVE_JPEG_H
292 else if(event->target==jpgType)
293 fxsaveJPG(ms,chart->getData(),chart->getWidth(),chart->getHeight(),75);
294 #endif
295 #ifdef HAVE_PNG_H
296 else if(event->target==pngType)
297 fxsavePNG(ms,chart->getData(),chart->getWidth(),chart->getHeight());
298 #endif
299 #ifdef HAVE_TIFF_H
300 else if(event->target==tifType)
301 fxsaveTIF(ms,chart->getData(),chart->getWidth(),chart->getHeight(),0);
302 #endif
303 #ifdef WIN32
304 // else if(event->target==imageType)
305 // fxsaveBMP(ms,chart->getData(),chart->getWidth(),chart->getHeight());
306 #endif
307
308 // Grab buffered image
309 ms.takeBuffer(data,size);
310
311 // Close memory stream
312 ms.close();
313
314 // Release pixels
315 chart->release();
316
317 // Set DND data
318 setDNDData(FROM_CLIPBOARD,event->target,data,size);
319 return 1;
320 }
321
322 return 0;
323 }
324
325
326 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)327 long FXChart::onPaint(FXObject*,FXSelector,void* ptr){
328 FXDCWindow dc(this,(FXEvent*)ptr);
329 dc.drawImage(chart,0,0);
330 return 1;
331 }
332
333
334 // Set fill style
setFillStyle(const FillStyle & fs)335 void FXChart::setFillStyle(const FillStyle& fs){
336 fill=fs;
337 recalc();
338 }
339
340
341 // Change help text
setHelpText(const FXString & text)342 void FXChart::setHelpText(const FXString& text){
343 help=text;
344 }
345
346
347 // Change tip text
setTipText(const FXString & text)348 void FXChart::setTipText(const FXString& text){
349 tip=text;
350 }
351
352
353 // Save data
save(FXStream & store) const354 void FXChart::save(FXStream& store) const {
355 FXComposite::save(store);
356 store << chart;
357 store << tip;
358 store << help;
359 }
360
361
362 // Load data
load(FXStream & store)363 void FXChart::load(FXStream& store){
364 FXComposite::load(store);
365 store >> chart;
366 store >> tip;
367 store >> help;
368 }
369
370
371 // Destroy
~FXChart()372 FXChart::~FXChart(){
373 delete chart;
374 chart=(FXImage*)-1L;
375 }
376
377 }
378