version update
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / nbodycuda / nbodywindow.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  * 
19  */
20
21 #include "bcdisplayinfo.h"
22 #include "clip.h"
23 #include "cwindow.h"
24 #include "cwindowgui.h"
25 #include "language.h"
26 #include "nbody.h"
27 #include "nbodywindow.h"
28 #include "mwindow.h"
29 #include "mwindowgui.h"
30 #include "pluginserver.h"
31 #include "theme.h"
32
33 static const char *display_modes[] = {
34         N_("point"),
35         N_("sprite"),
36         N_("color"),
37 };
38 static const int num_display_modes = sizeof(display_modes)/sizeof(*display_modes);
39
40 N_BodyWindow::N_BodyWindow(N_BodyMain *plugin)
41  : PluginClientWindow(plugin, xS(240), yS(200), xS(240), yS(200), 0)
42 {
43         this->plugin = plugin; 
44         press_x = press_y = 0;
45         button_no = 0;
46         pending_config = 0;
47 }
48
49 N_BodyWindow::~N_BodyWindow()
50 {
51 }
52
53 void N_BodyWindow::create_objects()
54 {
55         int x = xS(10), y = yS(10), pad = xS(5);
56         int x1 = xS(100);
57         BC_Title *title;
58         add_subwindow(title = new BC_Title(x,y, _("NBody"), MEDIUMFONT, YELLOW));
59         y += title->get_h() + 2*pad;
60         add_subwindow(title = new BC_Title(x,y, _("set demo:")));
61         set_demo = new N_BodySetDemo(this, x1,y, "0");
62         set_demo->create_objects();
63         y += set_demo->get_h() + pad;
64         add_subwindow(title = new BC_Title(x,y, _("draw mode:")));
65         set_mode = new N_BodySetMode(this, x1,y, _(display_modes[plugin->config.mode]));
66         set_mode->create_objects();
67         y += set_mode->get_h() + pad;
68         add_subwindow(title = new BC_Title(x,y, _("numBodies:")));
69         char text[BCSTRLEN];
70         sprintf(text, "%d", plugin->config.numBodies);
71         num_bodies = new N_BodyNumBodies(this, x1,y, text);
72         num_bodies->create_objects();
73         y += num_bodies->get_h() + pad;
74         add_subwindow(drag = new N_BodyDrag(this, x, y));
75         y += drag->get_h() + pad;
76         add_subwindow(reset = new N_BodyReset(this, x, y));
77         show_window();
78 }
79
80 void N_BodyWindow::update_gui()
81 {
82         set_mode->update(_(display_modes[plugin->config.mode]));
83         char text[BCSTRLEN];
84         sprintf(text, "%d", plugin->config.numBodies);
85         num_bodies->update(text);
86 }
87
88
89 void N_BodyWindow::send_configure_change()
90 {
91         pending_config = 0;
92         plugin->send_configure_change();
93 }
94
95 int N_BodyWindow::grab_event(XEvent *event)
96 {
97         int ret = do_grab_event(event);
98         if( pending_config && !grab_event_count() )
99                 send_configure_change();
100         return ret;
101 }
102
103 int N_BodyWindow::do_grab_event(XEvent *event)
104 {
105         switch( event->type ) {
106         case ButtonPress: break;
107         case ButtonRelease: break;
108         case MotionNotify: break;
109         default:
110                 return 0;
111         }
112
113         MWindow *mwindow = plugin->server->mwindow;
114         CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
115         CWindowCanvas *canvas = cwindow_gui->canvas;
116         int cursor_x, cursor_y;
117         cwindow_gui->get_relative_cursor(cursor_x, cursor_y);
118         cursor_x -= canvas->view_x;
119         cursor_y -= canvas->view_y;
120         float output_x = cursor_x, output_y = cursor_y;
121         canvas->canvas_to_output(mwindow->edl, 0, output_x, output_y);
122
123         if( !button_no ) {
124                 if( cursor_x < 0 || cursor_x >= canvas->view_w ||
125                     cursor_y < 0 || cursor_y >= canvas->view_h )
126                         return 0;
127         }
128
129         switch( event->type ) {
130         case ButtonPress:
131                 if( button_no ) return 0;
132                 press_x = output_x;  press_y = output_y;
133                 button_no = event->xbutton.button;
134                 break;
135         case ButtonRelease:
136                 if( !button_no ) return 0;
137                 button_no = 0;
138                 return 1;
139         case MotionNotify: {
140                 if( !button_no ) return 0;
141                 N_BodyConfig &config = plugin->config;
142                 double dx = (double)(press_x - output_x);
143                 double dy = (double)(press_y - output_y);
144                 press_x = output_x;  press_y = output_y;
145                 switch( button_no ) {
146                 case LEFT_BUTTON: {
147                         config.trans[0] += dx / 5.0f;
148                         config.trans[1] -= dy / 5.0f;
149                         break; }
150                 case MIDDLE_BUTTON: {
151                         double s = 0.5f * fabs(config.trans[2]);
152                         if( s < 0.1 ) s = 0.1;
153                         config.trans[2] += (dy / 100.0f) * s;
154                         break; }
155                 case RIGHT_BUTTON: {
156                         config.rot[0] += dy / 5.0f;
157                         config.rot[1] += dx / 5.0f;
158                         break; }
159                 }
160                 pending_config = 1;
161                 break; }
162         default:
163                 return 0;
164         }
165
166         return 1;
167 }
168
169 void N_BodyWindow::done_event(int result)
170 {
171         ungrab(client->server->mwindow->cwindow->gui);
172 }
173
174 N_BodyDrag::N_BodyDrag(N_BodyWindow *gui, int x, int y)
175  : BC_CheckBox(x, y, 0, _("Drag"))
176 {
177         this->gui = gui;
178 }
179 int N_BodyDrag::handle_event()
180 {
181         CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
182         if( get_value() ) {
183                 if( !gui->grab(cwindow_gui) ) {
184                         update(*value = 0);
185                         flicker(10,50);
186                 }
187         }
188         else
189                 gui->ungrab(cwindow_gui);
190         return 1;
191 }
192 int N_BodyDrag::handle_ungrab()
193 {
194         CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
195         int ret = gui->ungrab(cwindow_gui);
196         if( ret ) update(*value = 0);
197         return ret;
198 }
199
200 N_BodySetMode::N_BodySetMode(N_BodyWindow *gui, int x, int y, const char *text)
201  : BC_PopupTextBox(gui, 0, text, x, y, xS(100), yS(160))
202 {
203         this->gui = gui;
204 }
205
206 void N_BodySetMode::create_objects()
207 {
208         BC_PopupTextBox::create_objects();
209         for( int i=0; i<num_display_modes; ++i )
210                 mode_items.append(new BC_ListBoxItem(_(display_modes[i])));
211         update_list(&mode_items);
212 }
213
214 int N_BodySetMode::handle_event()
215 {
216         N_BodyMain *plugin = gui->plugin;
217         plugin->config.mode = get_number();
218         plugin->send_configure_change();
219         return 1;
220 }
221
222
223 N_BodySetDemo::N_BodySetDemo(N_BodyWindow *gui, int x, int y, const char *text)
224  : BC_PopupTextBox(gui, 0, text, x, y, xS(100), yS(160))
225 {
226         this->gui = gui;
227 }
228
229 void N_BodySetDemo::create_objects()
230 {
231         BC_PopupTextBox::create_objects();
232         for( int i=0; i<N_BodyParams::num_demos; ++i ) {
233                 char text[BCSTRLEN];  sprintf(text,"%d",i);
234                 demo_items.append(new BC_ListBoxItem(text));
235         }
236         update_list(&demo_items);
237 }
238
239 int N_BodySetDemo::handle_event()
240 {
241         N_BodyMain *plugin = gui->plugin;
242         plugin->selectDemo(get_number());
243         gui->update_gui();
244         plugin->send_configure_change();
245         return 1;
246 }
247
248 N_BodyNumBodies::N_BodyNumBodies(N_BodyWindow *gui, int x, int y, const char *text)
249  : BC_PopupTextBox(gui, 0, text, x, y, xS(100), yS(160))
250 {
251         this->gui = gui;
252 }
253
254 void N_BodyNumBodies::create_objects()
255 {
256         BC_PopupTextBox::create_objects();
257         for( int i=0; i<8; ++i ) {
258                 char text[BCSTRLEN];  sprintf(text,"%d",1<<(i+6));
259                 num_body_items.append(new BC_ListBoxItem(text));
260         }
261         update_list(&num_body_items);
262 }
263
264 int N_BodyNumBodies::handle_event()
265 {
266         N_BodyMain *plugin = gui->plugin;
267         int i = get_number();
268         int n = i >= 0 ? (1 << (i+6)) : atoi(get_text());
269         bclamp(n, 0x10,0x4000);
270         plugin->config.numBodies = n;
271         plugin->send_configure_change();
272         return 1;
273 }
274
275 N_BodyReset::N_BodyReset(N_BodyWindow *gui, int x, int y)
276  : BC_GenericButton(x, y, _("Reset"))
277 {
278         this->gui = gui;
279 }
280 N_BodyReset::~N_BodyReset()
281 {
282 }
283
284 int N_BodyReset::handle_event()
285 {
286         N_BodyMain *plugin = gui->plugin;
287         plugin->config.reset();
288         gui->update_gui();
289         gui->send_configure_change();
290         return 1;
291 }
292