4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <sys/types.h>
34 #include "empty_svg.h"
38 // 1 = update from client, 2 = client closes, 3 = quit
42 SvgWin::SvgWin(SvgMain *client)
43 : PluginClientWindow(client, 420, 210, 420, 210, 1)
45 this->client = client;
53 void SvgWin::create_objects()
58 add_tool(title = new BC_Title(x0, y, _("Out X:")));
59 int x1 = x0 + title->get_w() + 10;
60 out_x = new SvgCoord(this, client, x1, y, &client->config.out_x);
61 out_x->create_objects();
62 int x2 = x1 + out_x->get_w() + 15;
63 add_tool(title = new BC_Title(x2, y, _("Out W:")));
64 int x3 = x2 + title->get_w() + 10;
65 out_w = new SvgCoord(this, client, x3, y, &client->config.out_w);
66 out_w->create_objects();
67 y += out_x->get_h() + 5;
69 add_tool(new BC_Title(x0, y, _("Out Y:")));
70 out_y = new SvgCoord(this, client, x1, y, &client->config.out_y);
71 out_y->create_objects();
72 add_tool(title = new BC_Title(x2, y, _("Out H:")));
73 out_h = new SvgCoord(this, client, x3, y, &client->config.out_h);
74 out_h->create_objects();
75 y += out_y->get_h() + 20;
77 add_tool(title = new BC_Title(x0, y, _("DPI:")));
78 dpi = new DpiValue(this, client, x1, y, &client->config.dpi);
79 dpi->create_objects();
80 add_tool(dpi_button = new DpiButton(this, client, x2, y));
81 dpi_button->create_objects();
82 y += dpi->get_h() + 20;
84 add_tool(svg_file_title = new BC_Title(x0, y, client->config.svg_file));
85 y += svg_file_title->get_h() + 5;
87 int64_t ms_time = stat(client->config.svg_file, &st) ? 0 :
88 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
89 char mtime[BCSTRLEN]; mtime[0] = 0;
91 time_t tm = ms_time/1000;
94 add_tool(svg_file_mstime = new BC_Title(x0, y, mtime));
95 y += svg_file_mstime->get_h() + 15;
97 y = get_h() - NewSvgButton::calculate_h() - 5;
98 add_tool(new_svg_button = new NewSvgButton(client, this, x0, y));
99 y = get_h() - EditSvgButton::calculate_h() - 5;
100 add_tool(edit_svg_button = new EditSvgButton(client, this, x0+300, y));
106 int SvgWin::close_event()
108 edit_svg_button->stop();
113 int SvgWin::hide_window(int flush)
115 edit_svg_button->stop();
116 return BC_WindowBase::hide_window(flush);
120 void SvgWin::update_gui(SvgConfig &config)
122 lock_window("SvgWin::update_gui");
123 out_x->update(config.out_x);
124 out_y->update(config.out_y);
125 out_w->update(config.out_w);
126 out_h->update(config.out_h);
127 dpi->update(config.dpi);
128 svg_file_title->update(config.svg_file);
129 char mtime[BCSTRLEN]; mtime[0] = 0;
130 if( config.ms_time > 0 ) {
131 time_t tm = config.ms_time/1000;
134 svg_file_mstime->update(mtime);
138 static void flicker(BC_GenericButton *btn, int n, int clr)
140 int color = btn->get_color();
142 btn->text_color(clr); btn->draw_face(1);
143 btn->sync_display(); usleep(100000);
144 btn->text_color(color); btn->draw_face(1);
145 btn->sync_display(); usleep(100000);
149 SvgCoord::SvgCoord(SvgWin *win, SvgMain *client, int x, int y, float *value)
150 : BC_TumbleTextBox(win, *value, (float)0, (float)3000, x, y, 100)
152 //printf("SvgWidth::SvgWidth %f\n", client->config.w);
153 this->client = client;
158 SvgCoord::~SvgCoord()
162 int SvgCoord::handle_event()
164 *value = atof(get_text());
165 client->send_configure_change();
169 NewSvgButton::NewSvgButton(SvgMain *client, SvgWin *window, int x, int y)
170 : BC_GenericButton(x, y, _("New/Open SVG..."))
172 this->client = client;
173 this->window = window;
176 int NewSvgButton::handle_event()
178 window->editing_lock.lock();
179 if( !window->editing ) {
181 window->editing_lock.unlock();
185 flicker(this, 5, RED);
186 window->editing_lock.unlock();
192 void NewSvgButton::run()
194 // ======================================= get path from user
196 //printf("NewSvgButton::run 1\n");
199 strncpy(filename, client->config.svg_file, sizeof(filename));
200 // Loop until file is chosen
202 char directory[1024];
203 strncpy(directory, client->config.svg_file, sizeof(directory));
204 char *cp = strrchr(directory, '/');
206 if( !directory[0] ) {
207 char *cp = getenv("HOME");
208 if( cp ) strncpy(directory, cp, sizeof(directory));
210 NewSvgWindow *new_window = new NewSvgWindow(client, window, directory);
211 new_window->create_objects();
212 new_window->update_filter("*.svg");
213 result = new_window->run_window();
214 const char *filepath = new_window->get_path(0);
215 strcpy(filename, filepath);
217 if( result || !filepath || !*filepath ) {
218 window->editing_lock.lock();
220 window->editing_lock.unlock();
221 return; // cancel or no filename given
224 // Extend the filename with .svg
225 if( strlen(filename) < 4 ||
226 strcasecmp(&filename[strlen(filename) - 4], ".svg") ) {
227 strcat(filename, ".svg");
230 if( !access(filename, R_OK) )
233 FILE *out = fopen(filename,"w");
235 unsigned long size = sizeof(empty_svg) - 4;
236 fwrite(empty_svg+4, size, 1, out);
241 } while(result); // file doesn't exist so repeat
243 strcpy(client->config.svg_file, filename);
245 client->config.ms_time = stat(filename, &st) ? 0 :
246 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
247 window->update_gui(client->config);
248 client->send_configure_change();
250 window->editing_lock.lock();
252 window->editing_lock.unlock();
257 EditSvgButton::EditSvgButton(SvgMain *client, SvgWin *window, int x, int y)
258 : BC_GenericButton(x, y, _("Edit")), Thread(1)
260 this->client = client;
261 this->window = window;
265 EditSvgButton::~EditSvgButton()
270 void EditSvgButton::stop()
274 struct fifo_struct fifo_buf;
275 fifo_buf.pid = getpid();
277 write(fh_fifo, &fifo_buf, sizeof(fifo_buf));
283 int EditSvgButton::handle_event()
286 window->editing_lock.lock();
287 if( !window->editing && client->config.svg_file[0] != 0 ) {
289 window->editing_lock.unlock();
293 flicker(this, 5, RED);
294 window->editing_lock.unlock();
299 void EditSvgButton::run()
301 // ======================================= get path from user
302 char filename_png[1024];
303 char filename_fifo[1024];
304 strcpy(filename_png, client->config.svg_file);
305 strcat(filename_png, ".png");
306 remove(filename_png);
307 strcpy(filename_fifo, filename_png);
308 strcat(filename_fifo, ".fifo");
309 remove(filename_fifo);
310 if( !mkfifo(filename_fifo, S_IRWXU) &&
311 (fh_fifo = ::open(filename_fifo, O_RDWR+O_NONBLOCK)) >= 0 ) {
312 SvgInkscapeThread inkscape_thread(this);
313 inkscape_thread.start();
315 while( inkscape_thread.running() && !done ) {
317 int64_t ms_time = stat(client->config.svg_file, &st) ? 0 :
318 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
319 if( client->config.ms_time != ms_time ) {
320 client->config.ms_time = ms_time;
321 client->send_configure_change();
323 // select(fh_fifo+1,rds,0,ers,tmo) does not work here
325 struct fifo_struct fifo_buf; fifo_buf.action = 1;
326 int ret = read(fh_fifo, &fifo_buf, sizeof(fifo_buf));
328 if( errno == EAGAIN ) continue;
332 if( ret != sizeof(fifo_buf) ) continue;
333 switch( fifo_buf.action ) {
335 case 2: printf(_("Inkscape has exited\n"));
337 case 3: printf(_("Plugin window has closed\n"));
344 perror(_("Error opening fifo file"));
345 remove(filename_fifo); // fifo destroyed on last close
347 window->editing_lock.lock();
349 window->editing_lock.unlock();
351 client->config.ms_time = stat(client->config.svg_file, &st) ? 0 :
352 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
353 client->send_configure_change();
356 SvgInkscapeThread::SvgInkscapeThread(EditSvgButton *edit)
362 SvgInkscapeThread::~SvgInkscapeThread()
368 void SvgInkscapeThread::run()
372 sprintf(command, "inkscape --with-gui %s", edit->client->config.svg_file);
373 printf(_("Running external SVG editor: %s\n"), command);
377 printf(_("External SVG editor finished\n"));
378 struct fifo_struct fifo_buf;
379 fifo_buf.pid = getpid();
381 write(edit->fh_fifo, &fifo_buf, sizeof(fifo_buf));
389 NewSvgWindow::NewSvgWindow(SvgMain *client, SvgWin *window, char *init_directory)
391 BC_WindowBase::get_resources()->filebox_h / 2,
393 _("SVG Plugin: Pick SVG file"),
394 _("Open an existing SVG file or create a new one"))
396 this->window = window;
399 NewSvgWindow::~NewSvgWindow() {}
402 DpiValue::DpiValue(SvgWin *win, SvgMain *client, int x, int y, float *value)
403 : BC_TumbleTextBox(win, *value, (float)10, (float)1000, x, y, 100)
405 //printf("SvgWidth::SvgWidth %f\n", client->config.w);
406 this->client = client;
411 DpiValue::~DpiValue()
415 int DpiValue::handle_event()
417 *value = atof(get_text());
422 DpiButton::DpiButton( SvgWin *window, SvgMain *client, int x, int y)
423 : BC_GenericButton(x, y, _("update dpi"))
425 this->client = client;
426 this->window = window;
429 DpiButton::~DpiButton()
433 int DpiButton::handle_event()
435 client->send_configure_change();