source: tags/old_import_filter/PGT/plot.cxx

Last change on this file was 8300, checked in by westram, 12 years ago
  • cppchecked (1.52)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1// Copyright (c) 2004 - 2005 Kai Bader <baderk@in.tum.de>
2//
3// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
6// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
7// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
8// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
10// CVS REVISION TAG  --  $Revision: 8300 $
11
12
13#include "plot.hxx"
14#include <locale.h>
15
16
17#define GNUPLOT_WINDOW_WIDTH  321
18#define GNUPLOT_WINDOW_HEIGHT 123
19
20
21/****************************************************************************
22*  PLOT - CONSTRUCTOR
23****************************************************************************/
24Plot::Plot(Display *d, Window w)
25{
26    // SET PARENT WINDOW (WHERE THE GNUPLOT WINDOW WILL BE EMBEDDED)
27    m_parent_display= d;
28    m_parent_window= w;
29
30    // RESERVE SPACE FOR THE GNUPLOT WINDOW TITLE
31    m_title= (char *)malloc(64*sizeof(char));
32
33    // INITIALIZE THE PIPE VARIABLES
34    m_command_pipe= NULL;
35    m_has_command_pipe= false;
36    m_data_pipe= NULL;
37    m_has_data_pipe= false;
38    m_temp_name= NULL;
39}
40
41
42/****************************************************************************
43*  PLOT - DESTRUCTOR
44****************************************************************************/
45Plot::~Plot()
46{
47    // CLOSE COMMAND PIPE (IF NEEDED)
48    if(m_has_command_pipe) close_command_pipe();
49
50    // FREE ALLOCATED SPACE
51    free(m_title);
52}
53
54
55/****************************************************************************
56*  PLOT - SET THE PARENT WINDOW
57****************************************************************************/
58void Plot::setParentWindow(Window w) { m_parent_window= w; }
59
60
61/****************************************************************************
62*  PLOT - EMBED GNUPLOT X11 WINDOW INTO ANOTHER WINDOW
63****************************************************************************/
64void Plot::embed()
65{
66    // DO NOT EMBED IF THE PARENT WINDOW ID IS NULL OR NO DISPLAY IS SET
67    if(!m_parent_window || !m_parent_display) return;
68
69    // CREATE AND INIT LOCAL VARIABLES
70    int countdown= 100;
71    XEvent event;
72    char *window_name;
73    m_gnuplot_window= 0;
74
75    // SET THE EVENT MASK TO 'SubstructureNotifyMask'
76    XSelectInput(m_parent_display, DefaultRootWindow(m_parent_display), SubstructureNotifyMask);
77
78    // LOOP WHILE COUNTDOWN > 0 (AVOIDS INFINITE LOOPS)
79    while(countdown)
80    {
81        // CAUTION:
82        // XNEXTEVENT BELOW ALSO CATCHES OTHER EVENTS AND REMOVES THEM FROM
83        // THE QUEUE. THIS MAY CAUSE PROBLEMS WITH OTHER WINDOWS/WIDGETS,
84        // I.E. FALSE REDRAWN WINDOWS OR LOST SIGNALS FROM WINDOWS/WIDGETS.
85
86        // WAIT FOR AN EVENT TO OCCUR
87        XNextEvent(m_parent_display, &event);
88
89        // IS IT A CREATENOTIFY EVENT?
90        if(event.type == CreateNotify)
91        {
92            // FETCH THE CREATEWINDOWEVENT STRUCT
93            XCreateWindowEvent cwe= event.xcreatewindow;
94
95            // FETCH THE NAME OF THE WINDOW WHICH THREW THE EVENT (POSSIBLY NULL)
96            XFetchName(m_parent_display, cwe.window, &window_name);
97
98            // IF THE NAME MATCHES OUR GNUPLOT WINDOW OR THE SIZE IS RIGHT
99            // MARK IT AND EXIT THE LOOP
100            if((window_name && (strcmp(window_name, m_title) == 0)) ||
101               ((cwe.width == GNUPLOT_WINDOW_WIDTH) && (cwe.height == GNUPLOT_WINDOW_HEIGHT)))
102            {
103                // GET THE WINDOW ID OF THE NEW GNUPLOT WINDOW
104                m_gnuplot_window= cwe.window;
105
106                // SET BORDER WIDTH TO 0 IF NECESSARY
107                if(cwe.border_width) XSetWindowBorderWidth(m_parent_display, m_gnuplot_window, 0);
108
109                // SET COUNTDOWN= 0 TO EXIT LOOP
110                countdown= 0;
111            }
112            else countdown--; // DECREASE LOOP COUNTER
113        }
114        else
115        {
116            // DECREASE LOOP COUNTER
117            countdown--;
118        }
119    }
120
121    // EXIT, IF WE WERE NOT ABLE TO FIND THE GNUPLOT WINDOW
122    if (!m_gnuplot_window) return;
123
124    // SYNC AND WITHDRAW THE ORIGINAL WINDOW
125    XSync(m_parent_display, false);
126    XWithdrawWindow(m_parent_display, m_gnuplot_window, 0);
127
128    // THE REPARENTING MUST BE TRIED MULTIPLE TIMES TO WORK.
129    // DON'T ASK ME WHY...
130    for(int c= 0; c < 100; c++)
131    {
132        XReparentWindow(m_parent_display, m_gnuplot_window, m_parent_window, 0, 0);
133        XSync(m_parent_display, false);
134    }
135
136    // SYNC AND MAP THE NEW GNUPLOT WINDOW
137    XMapWindow(m_parent_display, m_gnuplot_window);
138    XSync(m_parent_display, false);
139}
140
141
142/****************************************************************************
143*  PLOT - RESIZE THE GNUPLOT WINDOW
144****************************************************************************/
145void Plot::resizeWindow(int x, int y, int width, int height)
146{
147    // RETURN IF NO WINDOW IS VISIBLE
148    if(!m_has_command_pipe) return;
149
150    // RESIZE THE GNUPLOT WINDOW
151    XMoveResizeWindow(m_parent_display, m_gnuplot_window, x, y, width, height);
152    XSync(m_parent_display, false);
153}
154
155
156/****************************************************************************
157*  PLOT - OPEN/INIT THE COMMAND PIPE
158****************************************************************************/
159FILE *Plot::open_command_pipe()
160{
161    // LOCAL GNUPLOT WINDOW ID (INCREMENTED BY EACH CALL TO MAKE IT UNIQUE)
162    static int m_local_ID= 0;
163
164    char *buf= (char *)malloc(1024*sizeof(char));
165
166    // CREATE GNUPLOT TITLE (NEEDED FOR LATER RECOGNITION)
167    sprintf(m_title, "plot%dclient%d", getpid(), ++m_local_ID);
168    sprintf(buf, "gnuplot -geometry %dx%d -title '%s'",
169            GNUPLOT_WINDOW_WIDTH, GNUPLOT_WINDOW_HEIGHT, m_title);
170
171    // CREATE A TEMPORARY FILENAME (USING MKSTEMP)
172    m_temp_name = (char *)malloc(17 * sizeof(char));
173    strcpy(m_temp_name, "/tmp/plot_XXXXXX");
174
175    FILE *result = NULL;
176    if ((mkstemp(m_temp_name)) != -1) {
177        // AS MKTEMP ALSO CREATES THE FILE ITSELF (WHAT WE DON'T WANT) REMOVE IT
178        // RIGHT AFTER ITS CREATION FOR FURTHER USE AS A PIPE
179        unlink(m_temp_name);
180
181        // CREATE A FIFO PIPE
182        if (mkfifo(m_temp_name, S_IRUSR | S_IWUSR) == 0) {
183            m_command_pipe     = popen(buf, "w");
184            m_has_command_pipe = true;
185            result             = m_command_pipe;
186        }
187    }
188
189    free(buf);
190    return result;
191}
192
193
194/****************************************************************************
195*  PLOT - CLOSE THE COMMAND PIPE
196****************************************************************************/
197void Plot::close_command_pipe()
198{
199    // CLOSE DATA PIPE (IF NEEDED)
200    if(m_has_data_pipe) close_data_pipe();
201
202    // CLOSE DATA PIPE
203    pclose(m_command_pipe);
204
205    // REMOVE TEMP FILE (WHICH WAS USED AS A PIPE)
206    unlink(m_temp_name);
207
208    if(m_temp_name) free(m_temp_name);
209    m_temp_name= NULL;
210
211    // SET COMMAND PIPE FLAG TO FALSE
212    m_has_command_pipe= false;
213}
214
215
216/****************************************************************************
217*  PLOT - OPEN THE DATA PIPE
218****************************************************************************/
219FILE *Plot::open_data_pipe()
220{
221    if(!m_has_command_pipe) return NULL;
222
223    fprintf(m_command_pipe, "plot \"%s\" with linespoints\n", m_temp_name);
224
225    fflush(m_command_pipe);
226    m_data_pipe= fopen(m_temp_name, "w");
227
228    // SET DATA PIPE FLAG TO TRUE
229    m_has_data_pipe= true;
230
231    return m_data_pipe;
232}
233
234
235/****************************************************************************
236*  PLOT - CLOSE THE DATA PIPE
237****************************************************************************/
238void Plot::close_data_pipe()
239{
240    if(!m_has_data_pipe) return;
241
242    // CLOSE DATA PIPE
243    fclose(m_data_pipe);
244
245    // SET DATA PIPE FLAG TO FALSE
246    m_has_data_pipe= false;
247}
248
249
250/****************************************************************************
251*  PLOT - SEND A STRING TO THE COMMAND PIPE
252****************************************************************************/
253void Plot::send_command_pipe(char *s)
254{
255    // RETURN, IF THERE IS NO OPEN COMMAND PIPE
256    if(!m_has_command_pipe) return;
257
258    // WRITE THE STRING S TO THE DATA PIPE
259    fputs(s, m_command_pipe);
260}
261
262
263/****************************************************************************
264*  PLOT - SEND A STRING TO THE DATA PIPE
265****************************************************************************/
266void Plot::send_data_pipe(char *s)
267{
268    // RETURN, IF THERE IS NO OPEN DATA PIPE
269    if(!m_has_data_pipe) return;
270
271    // WRITE THE STRING S TO THE DATA PIPE
272    fputs(s, m_data_pipe);
273}
274
275
276/****************************************************************************
277*  PLOT - CREATE A DEMO PLOT (FOR TESTING PURPOSES ONLY)
278****************************************************************************/
279void Plot::demo()
280{
281    // AVOID WRONG FLOAT OUTPUT DUE TO GERMAN LOCALES ( ',' -> '.')
282    setlocale(LC_ALL, "C");
283
284    if(!open_command_pipe()) return;
285
286    send_command_pipe(const_cast<char*>("set title \"Überschrift - Proteomdaten\"\n"));
287    send_command_pipe(const_cast<char*>("set xlabel \"Protein\"\n"));
288    send_command_pipe(const_cast<char*>("set ylabel \"Abweichung\"\n"));
289
290    if(!open_data_pipe()) return;
291
292    double a, b;
293
294    // FIRST DATASET
295    for (int i= 1; i < 20; i++)
296    {
297        a= i / 10.0;
298        b= cos(a);
299
300        fprintf(m_data_pipe, "%f %f\n", a, b);
301    }
302
303    // EMPTY LINE (SEPARATOR BETWEEN DATASETS)
304    fprintf(m_data_pipe, "\n");
305
306    // SECOND DATASET
307    for (int i= 1; i < 20; i++)
308    {
309        a= i / 10.0;
310        b= (double)(rand()%10);
311
312        fprintf(m_data_pipe, "%f %f\n", a, b);
313    }
314
315    close_data_pipe();
316
317    // RESET LOCALES
318    setlocale(LC_ALL, "");
319
320    // DEBUG
321    embed();
322    // DEBUG
323}
324
Note: See TracBrowser for help on using the repository browser.