1 /* a plot widget, plus some navigation stuff
2 */
3
4 /*
5
6 Copyright (C) 1991-2003 The National Gallery
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program 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
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 */
23
24 /*
25
26 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27
28 */
29
30 /*
31 #define DEBUG_EVENT
32 #define DEBUG
33 */
34
35 #include "ip.h"
36
37 #ifdef HAVE_LIBGOFFICE
38
39 static GtkBinClass *parent_class = NULL;
40
41 enum {
42 SIG_MOUSE_MOVE, /* mose drag, axies cods */
43 SIG_LAST
44 };
45
46 static guint plotpresent_signals[SIG_LAST] = { 0 };
47
48 static void
plotpresent_mouse_move(Plotpresent * plotpresent,double x,double y)49 plotpresent_mouse_move( Plotpresent *plotpresent, double x, double y )
50 {
51 g_signal_emit( G_OBJECT( plotpresent ),
52 plotpresent_signals[SIG_MOUSE_MOVE], 0, x, y );
53 }
54
55 static void
plotpresent_destroy(GtkObject * object)56 plotpresent_destroy( GtkObject *object )
57 {
58 Plotpresent *plotpresent;
59
60 g_return_if_fail( object != NULL );
61 g_return_if_fail( IS_PLOTPRESENT( object ) );
62
63 plotpresent = PLOTPRESENT( object );
64
65 #ifdef DEBUG
66 printf( "plotpresent_destroy: %p\n", plotpresent );
67 #endif /*DEBUG*/
68
69 /* My instance destroy stuff.
70 */
71 UNREF( plotpresent->grend );
72
73 GTK_OBJECT_CLASS( parent_class )->destroy( object );
74 }
75
76 static void
plotpresent_size_request(GtkWidget * widget,GtkRequisition * requisition)77 plotpresent_size_request( GtkWidget *widget, GtkRequisition *requisition )
78 {
79 GtkBin *bin = GTK_BIN( widget );
80
81 if( bin->child && GTK_WIDGET_VISIBLE( bin->child ) )
82 gtk_widget_size_request( bin->child, requisition );
83 }
84
85 static void
plotpresent_size_allocate(GtkWidget * widget,GtkAllocation * allocation)86 plotpresent_size_allocate( GtkWidget *widget, GtkAllocation *allocation )
87 {
88 GtkBin *bin = GTK_BIN( widget );
89
90 if( bin->child && GTK_WIDGET_VISIBLE( bin->child ) )
91 gtk_widget_size_allocate( bin->child, allocation );
92 }
93
94 /* Spot mouse motion events, to update status bar.
95 */
96 static gboolean
plotpresent_motion_notify_event(GtkWidget * widget,GdkEventMotion * event)97 plotpresent_motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
98 {
99 Plotpresent *plotpresent = PLOTPRESENT( widget );
100 GtkAllocation *allocation =
101 >K_WIDGET( plotpresent->canvas )->allocation;
102
103 GogView *view;
104 GSList *axes;
105 GogAxis *x_axis;
106 GogAxis *y_axis;
107 GogChartMap *map;
108
109 #ifdef DEBUG_EVENT
110 printf( "plotpresent_motion_notify_event: %p\n", plotpresent );
111 printf( "event->x = %g, event->y = %g\n", event->x, event->y );
112 #endif /*DEBUG_EVENT*/
113
114 gog_renderer_update( plotpresent->grend,
115 allocation->width, allocation->height );
116
117 g_object_get( G_OBJECT( plotpresent->grend ), "view", &view, NULL );
118 view = gog_view_find_child_view( view,
119 GOG_OBJECT( plotpresent->gplot ) );
120
121 axes = gog_chart_get_axes( plotpresent->gchart, GOG_AXIS_X );
122 x_axis = GOG_AXIS( axes->data );
123 g_slist_free( axes );
124
125 axes = gog_chart_get_axes( plotpresent->gchart, GOG_AXIS_Y );
126 y_axis = GOG_AXIS( axes->data );
127 g_slist_free( axes );
128
129 map = gog_chart_map_new( plotpresent->gchart, &(view->allocation),
130 x_axis, y_axis, NULL, FALSE );
131
132 if( gog_chart_map_is_valid( map ) &&
133 event->x >= view->allocation.x &&
134 event->x < view->allocation.x + view->allocation.w &&
135 event->y >= view->allocation.y &&
136 event->y < view->allocation.y + view->allocation.h ) {
137 GogAxisMap *x_map;
138 GogAxisMap *y_map;
139 double x;
140 double y;
141
142 x_map = gog_chart_map_get_axis_map( map, 0 );
143 y_map = gog_chart_map_get_axis_map( map, 1 );
144 x = gog_axis_map_from_view( x_map, event->x );
145 y = gog_axis_map_from_view( y_map, event->y );
146
147 plotpresent_mouse_move( plotpresent, x, y );
148 }
149
150 gog_chart_map_free( map );
151
152 return( FALSE );
153 }
154
155 static void
plotpresent_class_init(PlotpresentClass * class)156 plotpresent_class_init( PlotpresentClass *class )
157 {
158 GtkObjectClass *object_class = (GtkObjectClass *) class;
159 GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
160
161 parent_class = g_type_class_peek_parent( class );
162
163 object_class->destroy = plotpresent_destroy;
164
165 widget_class->size_request = plotpresent_size_request;
166 widget_class->size_allocate = plotpresent_size_allocate;
167
168 widget_class->motion_notify_event = plotpresent_motion_notify_event;
169
170 /* Create signals.
171 */
172 plotpresent_signals[SIG_MOUSE_MOVE] = g_signal_new( "mouse_move",
173 G_OBJECT_CLASS_TYPE( class ),
174 G_SIGNAL_RUN_FIRST,
175 G_STRUCT_OFFSET( PlotpresentClass, mouse_move ),
176 NULL, NULL,
177 nip_VOID__DOUBLE_DOUBLE,
178 G_TYPE_NONE, 2,
179 G_TYPE_DOUBLE, G_TYPE_DOUBLE );
180
181 /* Init methods.
182 */
183 }
184
185 static void
plotpresent_init(Plotpresent * plotpresent)186 plotpresent_init( Plotpresent *plotpresent )
187 {
188 #ifdef DEBUG
189 printf( "plotpresent_init: %p\n", plotpresent );
190 #endif /*DEBUG*/
191
192 plotpresent->gplot = NULL;
193
194 plotpresent->canvas = go_graph_widget_new( NULL );
195 gtk_container_add( GTK_CONTAINER( plotpresent ), plotpresent->canvas );
196 gtk_widget_show( GTK_WIDGET( plotpresent->canvas ) );
197
198 plotpresent->ggraph = go_graph_widget_get_graph(
199 GO_GRAPH_WIDGET( plotpresent->canvas ) );
200 plotpresent->gchart = go_graph_widget_get_chart(
201 GO_GRAPH_WIDGET( plotpresent->canvas ) );
202 gtk_widget_add_events( plotpresent->canvas,
203 GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
204
205 /* You'd think we could set up the axies too, but we can't get them
206 * from the chart until it's realized. Wait for the first refresh.
207 */
208
209 plotpresent->grend = gog_renderer_new( plotpresent->ggraph );
210 }
211
212 GType
plotpresent_get_type(void)213 plotpresent_get_type( void )
214 {
215 static GType type = 0;
216
217 if( !type ) {
218 static const GTypeInfo info = {
219 sizeof( PlotpresentClass ),
220 NULL, /* base_init */
221 NULL, /* base_finalize */
222 (GClassInitFunc) plotpresent_class_init,
223 NULL, /* class_finalize */
224 NULL, /* class_data */
225 sizeof( Plotpresent ),
226 32, /* n_preallocs */
227 (GInstanceInitFunc) plotpresent_init,
228 };
229
230 type = g_type_register_static( GTK_TYPE_BIN,
231 "Plotpresent", &info, 0 );
232 }
233
234 return( type );
235 }
236
237 static void
plotpresent_build_plot(Plotpresent * plotpresent)238 plotpresent_build_plot( Plotpresent *plotpresent )
239 {
240 Plotmodel *plotmodel = plotpresent->plotmodel;
241 Plot *plot = plotmodel->plot;
242
243 #ifdef DEBUG
244 printf( "plotpresent_build_plot: %p\n", plotpresent );
245 #endif /*DEBUG*/
246
247 GOG_UNREF( plotpresent->gplot );
248
249 plotpresent->gplot = plot_new_gplot( plot );
250 gog_object_add_by_name( GOG_OBJECT( plotpresent->gchart ),
251 "Plot", GOG_OBJECT( plotpresent->gplot ) );
252
253 plot_style_main( plot, plotpresent->gchart );
254 }
255
256 static void
plotpresent_changed_cb(Plotmodel * plotmodel,Plotpresent * plotpresent)257 plotpresent_changed_cb( Plotmodel *plotmodel, Plotpresent *plotpresent )
258 {
259 Plot *plot = plotmodel->plot;
260
261 #ifdef DEBUG
262 printf( "plotpresent_changed_cb: %p\n", plotpresent );
263 #endif /*DEBUG*/
264
265 /* Can refresh before model build.
266 */
267 if( plot->rows == 0 ||
268 plot->columns == 0 )
269 return;
270
271 /* Rebuild plot and data.
272 */
273 plotpresent_build_plot( plotpresent );
274 }
275
276 static void
plotpresent_link(Plotpresent * plotpresent,Plotmodel * plotmodel)277 plotpresent_link( Plotpresent *plotpresent, Plotmodel *plotmodel )
278 {
279 /* All the model parts for our set of views.
280 */
281 plotpresent->plotmodel = plotmodel;
282 g_signal_connect( G_OBJECT( plotmodel ), "changed",
283 G_CALLBACK( plotpresent_changed_cb ), plotpresent );
284 }
285
286 Plotpresent *
plotpresent_new(Plotmodel * plotmodel)287 plotpresent_new( Plotmodel *plotmodel )
288 {
289 Plotpresent *plotpresent = gtk_type_new( TYPE_PLOTPRESENT );
290
291 plotpresent_link( plotpresent, plotmodel );
292
293 return( plotpresent );
294 }
295
296 #endif /*HAVE_LIBGOFFICE*/
297