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 		&GTK_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