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