1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 */
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is Eek Preview Stuffs.
18 *
19 * The Initial Developer of the Original Code is
20 * Jon A. Cruz.
21 * Portions created by the Initial Developer are Copyright (C) 2005
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
40 #include <gtk/gtk.h>
41 #include "eek-preview.h"
43 #define PRIME_BUTTON_MAGIC_NUMBER 1
45 #define FOCUS_PROP_ID 1
49 static void eek_preview_class_init( EekPreviewClass *klass );
50 static void eek_preview_init( EekPreview *preview );
52 static GtkWidgetClass* parent_class = 0;
54 void eek_preview_set_color( EekPreview* preview, int r, int g, int b )
55 {
56 preview->_r = r;
57 preview->_g = g;
58 preview->_b = b;
59 }
62 GType eek_preview_get_type(void)
63 {
64 static GType preview_type = 0;
66 if (!preview_type) {
67 static const GTypeInfo preview_info = {
68 sizeof( EekPreviewClass ),
69 NULL, /* base_init */
70 NULL, /* base_finalize */
71 (GClassInitFunc)eek_preview_class_init,
72 NULL, /* class_finalize */
73 NULL, /* class_data */
74 sizeof( EekPreview ),
75 0, /* n_preallocs */
76 (GInstanceInitFunc)eek_preview_init,
77 NULL /* value_table */
78 };
81 preview_type = g_type_register_static( GTK_TYPE_DRAWING_AREA, "EekPreview", &preview_info, (GTypeFlags)0 );
82 }
84 return preview_type;
85 }
87 GtkWidget* eek_preview_area_new(void)
88 {
89 return NULL;
90 }
92 static void eek_preview_size_request( GtkWidget* widget, GtkRequisition* req )
93 {
94 gint width = 0;
95 gint height = 0;
96 EekPreview* preview = EEK_PREVIEW(widget);
97 gboolean worked = gtk_icon_size_lookup( preview->_size, &width, &height );
98 if ( !worked ) {
99 width = 16;
100 height = 16;
101 }
102 if ( preview->_view == VIEW_TYPE_LIST ) {
103 width *= 3;
104 }
105 req->width = width;
106 req->height = height;
107 }
109 enum {
110 CLICKED_SIGNAL,
111 ALTCLICKED_SIGNAL,
112 LAST_SIGNAL
113 };
116 static guint eek_preview_signals[LAST_SIGNAL] = { 0 };
119 gboolean eek_preview_expose_event( GtkWidget* widget, GdkEventExpose* event )
120 {
121 /* g_message("Exposed!!! %s", GTK_WIDGET_HAS_FOCUS(widget) ? "XXX" : "---" ); */
122 gint insetX = 0;
123 gint insetY = 0;
125 /*
126 gint lower = widget->allocation.width;
127 lower = (widget->allocation.height < lower) ? widget->allocation.height : lower;
128 if ( lower > 16 ) {
129 insetX++;
130 if ( lower > 18 ) {
131 insetX++;
132 if ( lower > 22 ) {
133 insetX++;
134 if ( lower > 24 ) {
135 insetX++;
136 if ( lower > 32 ) {
137 insetX++;
138 }
139 }
140 }
141 }
142 insetY = insetX;
143 }
144 */
146 if ( GTK_WIDGET_DRAWABLE( widget ) ) {
147 GtkStyle* style = gtk_widget_get_style( widget );
149 if ( insetX > 0 || insetY > 0 ) {
150 gtk_paint_flat_box( style,
151 widget->window,
152 (GtkStateType)GTK_WIDGET_STATE(widget),
153 GTK_SHADOW_NONE,
154 NULL,
155 widget,
156 NULL,
157 0, 0,
158 widget->allocation.width, widget->allocation.height);
159 }
161 GdkGC *gc = gdk_gc_new( widget->window );
162 EekPreview* preview = EEK_PREVIEW(widget);
163 GdkColor fg = {0, preview->_r, preview->_g, preview->_b};
164 gdk_colormap_alloc_color( gdk_colormap_get_system(), &fg, FALSE, TRUE );
166 gdk_gc_set_foreground( gc, &fg );
168 gdk_draw_rectangle( widget->window,
169 gc,
170 TRUE,
171 insetX, insetY,
172 widget->allocation.width - (insetX * 2), widget->allocation.height - (insetY * 2) );
174 if ( GTK_WIDGET_HAS_FOCUS(widget) ) {
175 gtk_paint_focus( style,
176 widget->window,
177 GTK_STATE_NORMAL,
178 NULL, /* GdkRectangle *area, */
179 widget,
180 NULL,
181 0 + 1, 0 + 1,
182 widget->allocation.width - 2, widget->allocation.height - 2 );
183 }
184 }
187 return FALSE;
188 }
191 static gboolean eek_preview_enter_cb( GtkWidget* widget, GdkEventCrossing* event )
192 {
193 if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
194 EekPreview* preview = EEK_PREVIEW(widget);
195 preview->_within = TRUE;
196 gtk_widget_set_state( widget, preview->_hot ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT );
197 }
198 return FALSE;
199 }
201 static gboolean eek_preview_leave_cb( GtkWidget* widget, GdkEventCrossing* event )
202 {
203 if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
204 EekPreview* preview = EEK_PREVIEW(widget);
205 preview->_within = FALSE;
206 gtk_widget_set_state( widget, GTK_STATE_NORMAL );
207 }
208 return FALSE;
209 }
211 /*
212 static gboolean eek_preview_focus_in_event( GtkWidget* widget, GdkEventFocus* event )
213 {
214 g_message("focus IN");
215 gboolean blip = parent_class->focus_in_event ? parent_class->focus_in_event(widget, event) : FALSE;
216 return blip;
217 }
219 static gboolean eek_preview_focus_out_event( GtkWidget* widget, GdkEventFocus* event )
220 {
221 g_message("focus OUT");
222 gboolean blip = parent_class->focus_out_event ? parent_class->focus_out_event(widget, event) : FALSE;
223 return blip;
224 }
225 */
227 static gboolean eek_preview_button_press_cb( GtkWidget* widget, GdkEventButton* event )
228 {
229 if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
230 EekPreview* preview = EEK_PREVIEW(widget);
232 if ( preview->_takesFocus && !GTK_WIDGET_HAS_FOCUS(widget) ) {
233 gtk_widget_grab_focus(widget);
234 }
236 if ( event->button == PRIME_BUTTON_MAGIC_NUMBER ) {
237 preview->_hot = TRUE;
238 if ( preview->_within ) {
239 gtk_widget_set_state( widget, GTK_STATE_ACTIVE );
240 }
241 }
242 }
244 return FALSE;
245 }
247 static gboolean eek_preview_button_release_cb( GtkWidget* widget, GdkEventButton* event )
248 {
249 if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
250 EekPreview* preview = EEK_PREVIEW(widget);
251 preview->_hot = FALSE;
252 gtk_widget_set_state( widget, GTK_STATE_NORMAL );
253 if ( preview->_within && event->button == PRIME_BUTTON_MAGIC_NUMBER ) {
254 gboolean isAlt = (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK;
256 if ( isAlt ) {
257 g_signal_emit( widget, eek_preview_signals[ALTCLICKED_SIGNAL], 0, 2 );
258 } else {
259 g_signal_emit( widget, eek_preview_signals[CLICKED_SIGNAL], 0 );
260 }
261 }
262 }
263 return FALSE;
264 }
266 gboolean eek_preview_key_press_event( GtkWidget* widget, GdkEventKey* event)
267 {
268 g_message("TICK");
269 return FALSE;
270 }
272 gboolean eek_preview_key_release_event( GtkWidget* widget, GdkEventKey* event)
273 {
274 g_message("tock");
275 return FALSE;
276 }
278 static void eek_preview_get_property( GObject *object,
279 guint property_id,
280 GValue *value,
281 GParamSpec *pspec)
282 {
283 GObjectClass* gobjClass = G_OBJECT_CLASS(parent_class);
284 switch ( property_id ) {
285 case FOCUS_PROP_ID:
286 {
287 EekPreview* preview = EEK_PREVIEW( object );
288 g_value_set_boolean( value, preview->_takesFocus );
289 }
290 break;
291 default:
292 {
293 if ( gobjClass->get_property ) {
294 gobjClass->get_property( object, property_id, value, pspec );
295 }
296 }
297 }
298 }
300 static void eek_preview_set_property( GObject *object,
301 guint property_id,
302 const GValue *value,
303 GParamSpec *pspec)
304 {
305 GObjectClass* gobjClass = G_OBJECT_CLASS(parent_class);
306 switch ( property_id ) {
307 case FOCUS_PROP_ID:
308 {
309 EekPreview* preview = EEK_PREVIEW( object );
310 gboolean val = g_value_get_boolean( value );
311 if ( val != preview->_takesFocus ) {
312 preview->_takesFocus = val;
313 }
314 }
315 break;
316 default:
317 {
318 if ( gobjClass->set_property ) {
319 gobjClass->set_property( object, property_id, value, pspec );
320 }
321 }
322 }
323 }
326 static gboolean eek_preview_popup_menu( GtkWidget* widget )
327 {
328 /* g_message("Do the popup!"); */
329 gboolean blip = parent_class->popup_menu ? parent_class->popup_menu(widget) : FALSE;
330 return blip;
331 }
334 static void eek_preview_class_init( EekPreviewClass *klass )
335 {
336 GObjectClass* gobjClass = G_OBJECT_CLASS(klass);
337 /*GtkObjectClass* objectClass = (GtkObjectClass*)klass;*/
338 GtkWidgetClass* widgetClass = (GtkWidgetClass*)klass;
340 gobjClass->set_property = eek_preview_set_property;
341 gobjClass->get_property = eek_preview_get_property;
343 /*objectClass->destroy = eek_preview_destroy;*/
345 parent_class = (GtkWidgetClass*)g_type_class_peek_parent( klass );
347 /*widgetClass->map = ;*/
348 /*widgetClass->unmap = ;*/
349 /*widgetClass->realize = ;*/
350 /*widgetClass->unrealize = ;*/
351 widgetClass->size_request = eek_preview_size_request;
352 /*widgetClass->size_allocate = ;*/
353 /*widgetClass->state_changed = ;*/
354 /*widgetClass->style_set = ;*/
355 /*widgetClass->grab_notify = ;*/
357 widgetClass->button_press_event = eek_preview_button_press_cb;
358 widgetClass->button_release_event = eek_preview_button_release_cb;
359 /*widgetClass->delete_event = ;*/
360 /*widgetClass->destroy_event = ;*/
361 widgetClass->expose_event = eek_preview_expose_event;
362 /* widgetClass->key_press_event = eek_preview_key_press_event; */
363 /* widgetClass->key_release_event = eek_preview_key_release_event; */
364 widgetClass->enter_notify_event = eek_preview_enter_cb;
365 widgetClass->leave_notify_event = eek_preview_leave_cb;
366 /*widgetClass->configure_event = ;*/
367 /*widgetClass->focus_in_event = eek_preview_focus_in_event;*/
368 /*widgetClass->focus_out_event = eek_preview_focus_out_event;*/
370 /* selection */
371 /*widgetClass->selection_get = ;*/
372 /*widgetClass->selection_received = ;*/
375 /* drag source: */
376 /*widgetClass->drag_begin = ;*/
377 /*widgetClass->drag_end = ;*/
378 /*widgetClass->drag_data_get = ;*/
379 /*widgetClass->drag_data_delete = ;*/
381 /* drag target: */
382 /*widgetClass->drag_leave = ;*/
383 /*widgetClass->drag_motion = ;*/
384 /*widgetClass->drag_drop = ;*/
385 /*widgetClass->drag_data_received = ;*/
387 /* For keybindings: */
388 widgetClass->popup_menu = eek_preview_popup_menu;
389 /*widgetClass->show_help = ;*/
391 /* Accessibility support: */
392 /*widgetClass->get_accessible = ;*/
393 /*widgetClass->screen_changed = ;*/
394 /*widgetClass->can_activate_accel = ;*/
397 eek_preview_signals[CLICKED_SIGNAL] =
398 g_signal_new( "clicked",
399 G_TYPE_FROM_CLASS( klass ),
400 (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
401 G_STRUCT_OFFSET( EekPreviewClass, clicked ),
402 NULL, NULL,
403 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 );
405 eek_preview_signals[ALTCLICKED_SIGNAL] =
406 g_signal_new( "alt-clicked",
407 G_TYPE_FROM_CLASS( klass ),
408 (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
409 G_STRUCT_OFFSET( EekPreviewClass, clicked ),
410 NULL, NULL,
411 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
412 1, G_TYPE_INT );
415 g_object_class_install_property( gobjClass,
416 FOCUS_PROP_ID,
417 g_param_spec_boolean(
418 "focus-on-click",
419 NULL,
420 "flag to grab focus when clicked",
421 TRUE,
422 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT)
423 )
424 );
425 }
427 gboolean eek_preview_get_focus_on_click( EekPreview* preview )
428 {
429 return preview->_takesFocus;
430 }
432 void eek_preview_set_focus_on_click( EekPreview* preview, gboolean focus_on_click )
433 {
434 if ( focus_on_click != preview->_takesFocus ) {
435 preview->_takesFocus = focus_on_click;
436 }
437 }
439 void eek_preview_set_details( EekPreview* preview, PreviewStyle prevstyle, ViewType view, GtkIconSize size )
440 {
441 preview->_prevstyle = prevstyle;
442 preview->_view = view;
443 preview->_size = size;
445 gtk_widget_queue_draw(GTK_WIDGET(preview));
446 }
448 static void eek_preview_init( EekPreview *preview )
449 {
450 GtkWidget* widg = GTK_WIDGET(preview);
451 GTK_WIDGET_SET_FLAGS( widg, GTK_CAN_FOCUS );
452 GTK_WIDGET_SET_FLAGS( widg, GTK_RECEIVES_DEFAULT );
454 gtk_widget_set_sensitive( widg, TRUE );
456 gtk_widget_add_events(widg, GDK_BUTTON_PRESS_MASK
457 | GDK_BUTTON_RELEASE_MASK
458 | GDK_KEY_PRESS_MASK
459 | GDK_KEY_RELEASE_MASK
460 | GDK_FOCUS_CHANGE_MASK
461 | GDK_ENTER_NOTIFY_MASK
462 | GDK_LEAVE_NOTIFY_MASK );
464 /* gtk_widget_add_events( widg, GDK_ALL_EVENTS_MASK );*/
466 preview->_r = 0x80;
467 preview->_g = 0x80;
468 preview->_b = 0xcc;
470 preview->_hot = FALSE;
471 preview->_within = FALSE;
472 preview->_takesFocus = FALSE;
474 preview->_prevstyle = PREVIEW_STYLE_ICON;
475 preview->_view = VIEW_TYPE_LIST;
476 preview->_size = GTK_ICON_SIZE_BUTTON;
478 /*
479 GdkColor color = {0};
480 color.red = (255 << 8) | 255;
482 GdkColor whack = {0};
483 whack.green = (255 << 8) | 255;
485 gtk_widget_modify_bg( widg, GTK_STATE_NORMAL, &color );
486 gtk_widget_modify_bg( widg, GTK_STATE_PRELIGHT, &whack );
487 */
489 /* GTK_STATE_ACTIVE, */
490 /* GTK_STATE_PRELIGHT, */
491 /* GTK_STATE_SELECTED, */
492 /* GTK_STATE_INSENSITIVE */
494 if ( 0 ) {
495 GdkColor color = {0,0,0,0};
497 color.red = 0xffff;
498 color.green = 0;
499 color.blue = 0xffff;
500 gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
501 gtk_widget_modify_bg(widg, GTK_STATE_ACTIVE, &color);
503 color.red = 0;
504 color.green = 0xffff;
505 color.blue = 0;
506 gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
507 gtk_widget_modify_bg(widg, GTK_STATE_SELECTED, &color);
509 color.red = 0xffff;
510 color.green = 0;
511 color.blue = 0;
512 gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
513 gtk_widget_modify_bg( widg, GTK_STATE_PRELIGHT, &color );
514 }
515 }
518 GtkWidget* eek_preview_new(void)
519 {
520 return GTK_WIDGET( g_object_new( EEK_PREVIEW_TYPE, NULL ) );
521 }