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
22 #include "bcdisplayinfo.h"
30 #include <sys/types.h>
35 #include "empty_svg.h"
39 // 1 = update from client, 2 = client closes, 3 = quit
43 SvgWin::SvgWin(SvgMain *client)
44 : PluginClientWindow(client, 300, 180, 300, 180, 1)
46 this->client = client;
54 void SvgWin::create_objects()
58 add_tool(title = new BC_Title(x, y, _("Out X:")));
59 int x1 = x + title->get_w() + 10;
60 out_x = new SvgCoord(this, client, x1, y, &client->config.out_x);
61 out_x->create_objects();
62 y += out_x->get_h() + 5;
63 add_tool(new BC_Title(x, y, _("Out Y:")));
64 out_y = new SvgCoord(this, client, x1, y, &client->config.out_y);
65 out_y->create_objects();
66 y += out_y->get_h() + 20;
68 add_tool(new_svg_button = new NewSvgButton(client, this, x, y));
69 add_tool(edit_svg_button = new EditSvgButton(client, this, x+190, y));
71 add_tool(svg_file_title = new BC_Title(x, y+=42, client->config.svg_file));
72 add_tool(svg_file_mstime = new BC_Title(x, y+=26, ""));
78 int SvgWin::close_event()
80 edit_svg_button->stop();
86 void SvgWin::update_gui(SvgConfig &config)
88 lock_window("SvgWin::update_gui");
89 out_x->update(config.out_x);
90 out_y->update(config.out_y);
91 svg_file_title->update(config.svg_file);
92 char mtime[BCSTRLEN]; mtime[0] = 0;
93 if( config.ms_time > 0 ) {
94 time_t tm = config.ms_time/1000;
97 svg_file_mstime->update(mtime);
101 static void flicker(BC_GenericButton *btn, int n, int clr)
103 int color = btn->get_color();
105 btn->text_color(clr); btn->draw_face(1);
106 btn->sync_display(); usleep(100000);
107 btn->text_color(color); btn->draw_face(1);
108 btn->sync_display(); usleep(100000);
112 SvgCoord::SvgCoord(SvgWin *win, SvgMain *client, int x, int y, float *value)
113 : BC_TumbleTextBox(win, *value, (float)0, (float)3000, x, y, 100)
115 //printf("SvgWidth::SvgWidth %f\n", client->config.w);
116 this->client = client;
121 SvgCoord::~SvgCoord()
125 int SvgCoord::handle_event()
127 *value = atof(get_text());
128 client->send_configure_change();
132 NewSvgButton::NewSvgButton(SvgMain *client, SvgWin *window, int x, int y)
133 : BC_GenericButton(x, y, _("New/Open SVG..."))
135 this->client = client;
136 this->window = window;
139 int NewSvgButton::handle_event()
141 window->editing_lock.lock();
142 if( !window->editing ) {
144 window->editing_lock.unlock();
148 flicker(this, 5, RED);
149 window->editing_lock.unlock();
155 void NewSvgButton::run()
157 // ======================================= get path from user
159 //printf("NewSvgButton::run 1\n");
162 strncpy(filename, client->config.svg_file, sizeof(filename));
163 // Loop until file is chosen
165 char directory[1024];
166 strncpy(directory, client->config.svg_file, sizeof(directory));
167 char *cp = strrchr(directory, '/');
169 if( !directory[0] ) {
170 char *cp = getenv("HOME");
171 if( cp ) strncpy(directory, cp, sizeof(directory));
173 NewSvgWindow *new_window = new NewSvgWindow(client, window, directory);
174 new_window->create_objects();
175 new_window->update_filter("*.svg");
176 result = new_window->run_window();
177 const char *filepath = new_window->get_path(0);
178 strcpy(filename, filepath);
180 if( result || !filepath || !*filepath ) {
181 window->editing_lock.lock();
183 window->editing_lock.unlock();
184 return; // cancel or no filename given
187 // Extend the filename with .svg
188 if(strlen(filename) < 4 ||
189 strcasecmp(&filename[strlen(filename) - 4], ".svg")) {
190 strcat(filename, ".svg");
193 if( !access(filename, R_OK) )
196 FILE *out = fopen(filename,"w");
198 unsigned long size = sizeof(empty_svg) - 4;
199 fwrite(empty_svg+4, size, 1, out);
204 } while(result); // file doesn't exist so repeat
206 strcpy(client->config.svg_file, filename);
208 client->config.ms_time = stat(filename, &st) ? 0 :
209 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
210 window->update_gui(client->config);
211 client->send_configure_change();
213 window->editing_lock.lock();
215 window->editing_lock.unlock();
220 EditSvgButton::EditSvgButton(SvgMain *client, SvgWin *window, int x, int y)
221 : BC_GenericButton(x, y, _("Edit")), Thread(1)
223 this->client = client;
224 this->window = window;
228 EditSvgButton::~EditSvgButton()
233 void EditSvgButton::stop()
237 struct fifo_struct fifo_buf;
238 fifo_buf.pid = getpid();
240 write(fh_fifo, &fifo_buf, sizeof(fifo_buf));
246 int EditSvgButton::handle_event()
249 window->editing_lock.lock();
250 if (!window->editing && client->config.svg_file[0] != 0)
253 window->editing_lock.unlock();
257 flicker(this, 5, RED);
258 window->editing_lock.unlock();
263 void EditSvgButton::run()
265 // ======================================= get path from user
266 char filename_png[1024];
267 char filename_fifo[1024];
268 strcpy(filename_png, client->config.svg_file);
269 strcat(filename_png, ".png");
270 remove(filename_png);
271 strcpy(filename_fifo, filename_png);
272 strcat(filename_fifo, ".fifo");
273 remove(filename_fifo);
274 if( !mkfifo(filename_fifo, S_IRWXU) &&
275 (fh_fifo = ::open(filename_fifo, O_RDWR+O_NONBLOCK)) >= 0 ) {
276 SvgInkscapeThread inkscape_thread(this);
277 inkscape_thread.start();
279 while( inkscape_thread.running() && !done ) {
281 int64_t ms_time = stat(client->config.svg_file, &st) ? 0 :
282 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
283 if( client->config.ms_time != ms_time ) {
284 client->config.ms_time = ms_time;
285 client->send_configure_change();
287 // select(fh_fifo+1,rds,0,ers,tmo) does not work here
289 struct fifo_struct fifo_buf; fifo_buf.action = 1;
290 int ret = read(fh_fifo, &fifo_buf, sizeof(fifo_buf));
292 if( errno == EAGAIN ) continue;
296 if( ret != sizeof(fifo_buf) ) continue;
297 switch( fifo_buf.action ) {
299 case 2: printf(_("Inkscape has exited\n"));
301 case 3: printf(_("Plugin window has closed\n"));
308 perror(_("Error opening fifo file"));
309 remove(filename_fifo); // fifo destroyed on last close
311 window->editing_lock.lock();
313 window->editing_lock.unlock();
315 client->config.ms_time = stat(client->config.svg_file, &st) ? 0 :
316 st.st_mtim.tv_sec*1000 + st.st_mtim.tv_nsec/1000000;
317 client->send_configure_change();
320 SvgInkscapeThread::SvgInkscapeThread(EditSvgButton *edit)
326 SvgInkscapeThread::~SvgInkscapeThread()
332 void SvgInkscapeThread::run()
336 sprintf(command, "inkscape --with-gui %s", edit->client->config.svg_file);
337 printf(_("Running external SVG editor: %s\n"), command);
341 printf(_("External SVG editor finished\n"));
342 struct fifo_struct fifo_buf;
343 fifo_buf.pid = getpid();
345 write(edit->fh_fifo, &fifo_buf, sizeof(fifo_buf));
353 NewSvgWindow::NewSvgWindow(SvgMain *client, SvgWin *window, char *init_directory)
355 BC_WindowBase::get_resources()->filebox_h / 2,
357 _("SVG Plugin: Pick SVG file"),
358 _("Open an existing SVG file or create a new one"))
360 this->window = window;
363 NewSvgWindow::~NewSvgWindow() {}