1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2006 Sebastien Granjoux
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "data_view.h"
23 #include "chunk_view.h"
25 #include "anjuta-marshal.h"
27 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
33 /* Size in pixel of border between text view widget */
34 #define ADDRESS_BORDER 4
35 #define ASCII_BORDER 2
36 #define SCROLLBAR_SPACING 4
47 GtkWidget
*goto_window
;
48 GtkWidget
*goto_entry
;
53 GtkTextBuffer
*adr_buffer
;
54 GtkTextBuffer
*data_buffer
;
55 GtkTextBuffer
*ascii_buffer
;
57 GtkAdjustment
*hadjustment
;
58 GtkAdjustment
*vadjustment
;
60 GtkAdjustment
* view_range
;
61 GtkAdjustment
* buffer_range
;
63 DmaDataBuffer
*buffer
;
74 struct _DmaDataViewClass
76 GtkContainerClass parent_class
;
82 PROP_0
, PROP_BUFFER
, N_PROPERTIES
84 static GParamSpec
*properties
[N_PROPERTIES
] = { NULL
, };
86 G_DEFINE_TYPE (DmaDataView
, dma_data_view
, GTK_TYPE_CONTAINER
);
89 *---------------------------------------------------------------------------*/
93 get_widget_char_size (GtkWidget
*widget
, gint
*width
, gint
*height
)
95 PangoFontMetrics
*metrics
;
96 PangoContext
*context
;
97 PangoFontDescription
*font_desc
;
99 font_desc
= pango_font_description_from_string ("Monospace 10");
101 context
= gtk_widget_get_pango_context (widget
);
102 metrics
= pango_context_get_metrics (context
,
103 /*widget->style->font_desc,*/
105 pango_context_get_language (context
));
107 *height
= PANGO_PIXELS (pango_font_metrics_get_ascent (metrics
) +
108 pango_font_metrics_get_descent (metrics
));
109 *width
= (pango_font_metrics_get_approximate_char_width (metrics
) + PANGO_SCALE
- 1) / PANGO_SCALE
;
110 pango_font_metrics_unref (metrics
);
111 pango_font_description_free (font_desc
);
116 get_css_padding_and_border (GtkWidget
*widget
,
119 GtkStyleContext
*context
;
123 context
= gtk_widget_get_style_context (widget
);
124 state
= gtk_widget_get_state_flags (widget
);
126 gtk_style_context_get_padding (context
, state
, border
);
127 gtk_style_context_get_border (context
, state
, &tmp
);
128 border
->top
+= tmp
.top
;
129 border
->right
+= tmp
.right
;
130 border
->bottom
+= tmp
.bottom
;
131 border
->left
+= tmp
.left
;
134 /* Goto address window
135 *---------------------------------------------------------------------------*/
138 dma_data_view_goto_window_hide (DmaDataView
*view
)
140 gtk_widget_hide (view
->goto_window
);
141 // gtk_entry_set_text (GTK_ENTRY (view->goto_entry), "");
145 dma_data_view_goto_delete_event (GtkWidget
*widget
,
149 g_return_val_if_fail (GTK_IS_WIDGET (widget
), FALSE
);
151 dma_data_view_goto_window_hide (view
);
157 dma_data_view_goto_key_press_event (GtkWidget
*widget
,
161 g_return_val_if_fail (GTK_IS_WIDGET (widget
), FALSE
);
162 g_return_val_if_fail (IS_DMA_DATA_VIEW (view
), FALSE
);
165 if (event
->keyval
== GDK_KEY_Escape
||
166 event
->keyval
== GDK_KEY_Tab
||
167 event
->keyval
== GDK_KEY_KP_Tab
||
168 event
->keyval
== GDK_KEY_ISO_Left_Tab
)
170 dma_data_view_goto_window_hide (view
);
174 /* Goto to address and close window */
175 if (event
->keyval
== GDK_KEY_Return
||
176 event
->keyval
== GDK_KEY_ISO_Enter
||
177 event
->keyval
== GDK_KEY_KP_Enter
)
183 text
= gtk_entry_get_text (GTK_ENTRY (view
->goto_entry
));
184 adr
= strtoul (text
, &end
, 0);
186 if ((*text
!= '\0') && (*end
== '\0'))
188 /* Valid input goto to address */
189 gtk_adjustment_set_value (view
->buffer_range
, adr
);
192 dma_data_view_goto_window_hide (view
);
200 dma_data_view_goto_position_func (DmaDataView
*view
)
204 GdkWindow
*window
= gtk_widget_get_window (GTK_WIDGET (view
));
205 GdkScreen
*screen
= gdk_window_get_screen (window
);
207 GdkRectangle monitor
;
209 monitor_num
= gdk_screen_get_monitor_at_window (screen
, window
);
210 gdk_screen_get_monitor_geometry (screen
, monitor_num
, &monitor
);
212 gtk_widget_realize (view
->goto_window
);
214 gdk_window_get_origin (window
, &win_x
, &win_y
);
215 x
= MAX(12, win_x
+ 12);
216 y
= MAX(12, win_y
+ 12);
218 gtk_window_move (GTK_WINDOW (view
->goto_window
), x
, y
);
221 /* Cut and paste from gtkwindow.c */
223 send_focus_change (GtkWidget
*widget
,
226 GdkEvent
*fevent
= gdk_event_new (GDK_FOCUS_CHANGE
);
228 fevent
->focus_change
.type
= GDK_FOCUS_CHANGE
;
229 fevent
->focus_change
.window
= g_object_ref (gtk_widget_get_window (widget
));
230 fevent
->focus_change
.in
= in
;
232 gtk_widget_send_focus_change (widget
, fevent
);
233 gdk_event_free (fevent
);
237 dma_data_view_goto_activate (GtkWidget
*menu_item
,
243 GtkWindowGroup
*toplevel_group
;
244 GtkWindowGroup
*goto_window_group
;
246 toplevel
= gtk_widget_get_toplevel (GTK_WIDGET (view
));
247 toplevel_group
= gtk_window_get_group (GTK_WINDOW (toplevel
));
248 goto_window_group
= gtk_window_get_group (GTK_WINDOW (view
->goto_window
));
250 if (view
->goto_window
!= NULL
)
253 gtk_window_group_add_window (toplevel_group
,
254 GTK_WINDOW (view
->goto_window
));
255 else if (goto_window_group
)
256 gtk_window_group_remove_window (goto_window_group
,
257 GTK_WINDOW (view
->goto_window
));
262 view
->goto_window
= gtk_window_new (GTK_WINDOW_POPUP
);
265 gtk_window_group_add_window (toplevel_group
,
266 GTK_WINDOW (view
->goto_window
));
268 gtk_window_set_modal (GTK_WINDOW (view
->goto_window
), TRUE
);
269 g_signal_connect (view
->goto_window
, "delete_event",
270 G_CALLBACK (dma_data_view_goto_delete_event
),
272 g_signal_connect (view
->goto_window
, "key_press_event",
273 G_CALLBACK (dma_data_view_goto_key_press_event
),
276 frame
= gtk_frame_new (NULL
);
277 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_ETCHED_IN
);
278 gtk_widget_show (frame
);
279 gtk_container_add (GTK_CONTAINER (view
->goto_window
), frame
);
281 vbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
282 gtk_widget_show (vbox
);
283 gtk_container_add (GTK_CONTAINER (frame
), vbox
);
284 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 3);
287 view
->goto_entry
= gtk_entry_new ();
288 gtk_entry_set_icon_from_stock (GTK_ENTRY (view
->goto_entry
),
289 GTK_ENTRY_ICON_PRIMARY
,
291 gtk_widget_show (view
->goto_entry
);
292 gtk_container_add (GTK_CONTAINER (vbox
),
295 gtk_widget_realize (view
->goto_entry
);
298 dma_data_view_goto_position_func (view
);
299 gtk_entry_set_text (GTK_ENTRY (view
->goto_entry
), "0x");
300 gtk_widget_show (view
->goto_window
);
302 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view
->address
), FALSE
);
303 gtk_widget_grab_focus (view
->goto_entry
);
304 send_focus_change (view
->goto_entry
, TRUE
);
305 gtk_editable_set_position (GTK_EDITABLE (view
->goto_entry
), -1);
309 *---------------------------------------------------------------------------*/
312 dma_data_view_address_size_request (DmaDataView
*view
,
313 GtkRequisition
*requisition
)
320 layout
= gtk_widget_create_pango_layout(view
->address
, text
);
321 pango_layout_get_pixel_size(layout
, &(requisition
->width
), &(requisition
->height
));
325 pango_layout_get_pixel_size(layout
, &width
, &height
);
326 if (width
> requisition
->width
) requisition
->width
= width
;
327 if (height
> requisition
->height
) requisition
->height
= height
;
328 } while (text
[0] == '9');
329 for (text
[0] = 'A'; text
[0] != 'G'; text
[0]++)
331 pango_layout_get_pixel_size(layout
, &width
, &height
);
332 if (width
> requisition
->width
) requisition
->width
= width
;
333 if (height
> requisition
->height
) requisition
->height
= height
;
335 g_object_unref(G_OBJECT(layout
));
337 requisition
->width
*= sizeof(view
->start
) * 2;
341 dma_data_view_data_size_request (DmaDataView
*view
,
342 GtkRequisition
*requisition
)
344 PangoContext
*context
;
345 PangoFontDescription
*font_desc
;
346 PangoFontMetrics
*metrics
;
348 context
= gtk_widget_get_pango_context (view
->data
);
349 gtk_style_context_get (gtk_widget_get_style_context (view
->data
),
350 gtk_widget_get_state_flags (view
->data
),
351 "font", &font_desc
, NULL
);
352 metrics
= pango_context_get_metrics (context
, font_desc
,
353 pango_context_get_language (context
));
355 requisition
->height
= PANGO_PIXELS (pango_font_metrics_get_ascent (metrics
) +
356 pango_font_metrics_get_descent (metrics
));
357 requisition
->width
= (pango_font_metrics_get_approximate_char_width (metrics
) + PANGO_SCALE
- 1) / PANGO_SCALE
;
358 pango_font_metrics_unref (metrics
);
362 dma_data_view_ascii_size_request (DmaDataView
*view
,
363 GtkRequisition
*requisition
)
365 PangoContext
*context
;
366 PangoFontDescription
*font_desc
;
367 PangoFontMetrics
*metrics
;
369 context
= gtk_widget_get_pango_context (view
->data
);
370 gtk_style_context_get (gtk_widget_get_style_context (view
->data
),
371 gtk_widget_get_state_flags (view
->data
),
372 "font", &font_desc
, NULL
);
373 metrics
= pango_context_get_metrics (context
, font_desc
,
374 pango_context_get_language (context
));
376 requisition
->height
= PANGO_PIXELS (pango_font_metrics_get_ascent (metrics
) +
377 pango_font_metrics_get_descent (metrics
));
378 requisition
->width
= (pango_font_metrics_get_approximate_char_width (metrics
) + PANGO_SCALE
- 1) / PANGO_SCALE
;
380 pango_font_metrics_unref (metrics
);
384 dma_data_view_value_changed (GtkAdjustment
*adj
,
389 value
= gtk_adjustment_get_value (adj
);
390 view
->start
= ((gulong
) value
) - (((gulong
) value
) % view
->bytes_by_line
);
391 dma_data_view_refresh (view
);
395 dma_data_view_populate_popup (GtkTextView
*widget
,
399 GtkWidget
*menu_item
;
402 menu_item
= gtk_menu_item_new ();
403 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu
), menu_item
);
404 gtk_widget_show (menu_item
);
406 /* create goto menu_item. */
407 menu_item
= gtk_menu_item_new_with_mnemonic (_("_Go to address"));
408 g_signal_connect (G_OBJECT (menu_item
), "activate",
409 G_CALLBACK (dma_data_view_goto_activate
), view
);
410 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu
), menu_item
);
411 gtk_widget_show (menu_item
);
415 dma_data_view_get_preferred_width (GtkWidget
*widget
,
416 gint
*minimum_width
, gint
*natural_width
)
418 DmaDataView
*view
= DMA_DATA_VIEW (widget
);
420 GtkRequisition child_requisition
;
421 GtkBorder css_border
;
423 gtk_widget_get_preferred_width (view
->range
, &width
, NULL
);
425 dma_data_view_address_size_request (view
, &child_requisition
);
426 width
+= child_requisition
.width
;
427 width
+= ADDRESS_BORDER
;
429 dma_data_view_data_size_request (view
, &child_requisition
);
430 width
+= child_requisition
.width
* view
->char_by_byte
;
431 width
+= ASCII_BORDER
;
433 dma_data_view_ascii_size_request (view
, &child_requisition
);
434 width
+= child_requisition
.width
;
436 width
+= SCROLLBAR_SPACING
;
438 get_css_padding_and_border (widget
, &css_border
);
439 width
+= css_border
.left
+ css_border
.right
;
441 *minimum_width
= *natural_width
= width
;
445 dma_data_view_get_preferred_height (GtkWidget
*widget
,
446 gint
*minimum_height
, gint
*natural_height
)
448 DmaDataView
*view
= DMA_DATA_VIEW (widget
);
450 GtkRequisition child_requisition
;
451 GtkBorder css_border
;
453 gtk_widget_get_preferred_height (view
->range
, &height
, NULL
);
455 dma_data_view_address_size_request (view
, &child_requisition
);
456 height
= MAX (height
, child_requisition
.height
);
458 dma_data_view_data_size_request (view
, &child_requisition
);
459 height
= MAX (height
, child_requisition
.height
);
461 dma_data_view_ascii_size_request (view
, &child_requisition
);
462 height
= MAX (height
, child_requisition
.height
);
464 get_css_padding_and_border (widget
, &css_border
);
465 height
+= css_border
.top
+ css_border
.bottom
;
467 *minimum_height
= *natural_height
= height
;
471 dma_data_view_size_allocate (GtkWidget
*widget
,
472 GtkAllocation
*allocation
)
474 DmaDataView
*view
= DMA_DATA_VIEW (widget
);
475 GtkAllocation child_allocation
;
476 GtkRequisition range_requisition
;
477 GtkRequisition address_requisition
;
478 GtkRequisition data_requisition
;
479 GtkRequisition ascii_requisition
;
480 GtkBorder css_border
;
485 gboolean need_fill
= FALSE
;
487 gtk_widget_set_allocation (widget
, allocation
);
489 gtk_widget_get_preferred_size (view
->range
, &range_requisition
, NULL
);
490 dma_data_view_address_size_request (view
, &address_requisition
);
491 dma_data_view_data_size_request (view
, &data_requisition
);
492 dma_data_view_ascii_size_request (view
, &ascii_requisition
);
493 get_css_padding_and_border (widget
, &css_border
);
495 /* Compute number of byte per line */
496 width
= allocation
->width
497 - (css_border
.left
+ css_border
.right
)
501 - range_requisition
.width
502 - address_requisition
.width
503 - data_requisition
.width
* view
->char_by_byte
504 - ascii_requisition
.width
;
506 step
= (ascii_requisition
.width
+ data_requisition
.width
* (view
->char_by_byte
+ 1));
507 for (bytes_by_line
= 1; width
>= step
* bytes_by_line
; bytes_by_line
*= 2)
509 width
-= step
* bytes_by_line
;
512 if (bytes_by_line
!= view
->bytes_by_line
)
515 view
->bytes_by_line
= bytes_by_line
;
518 /* Compute number of line by page */
519 height
= allocation
->height
- (css_border
.top
+ css_border
.bottom
);
521 if (view
->line_by_page
!= (height
/ address_requisition
.height
))
524 view
->line_by_page
= (height
/ address_requisition
.height
);
527 child_allocation
.y
= allocation
->y
+ css_border
.top
;
528 child_allocation
.height
= MAX (1, allocation
->height
529 - (css_border
.top
+ css_border
.bottom
));
532 child_allocation
.x
= allocation
->x
+ allocation
->width
533 - css_border
.right
- range_requisition
.width
;
534 child_allocation
.width
= range_requisition
.width
;
535 gtk_widget_size_allocate (view
->range
, &child_allocation
);
537 child_allocation
.x
= allocation
->x
+ css_border
.right
;
540 child_allocation
.width
= address_requisition
.width
;
541 gtk_widget_size_allocate (view
->address
, &child_allocation
);
542 child_allocation
.x
+= child_allocation
.width
;
544 child_allocation
.x
+= ADDRESS_BORDER
;
548 child_allocation
.width
= (view
->bytes_by_line
* (view
->char_by_byte
+ 1) - 1) * data_requisition
.width
;
549 gtk_widget_size_allocate (view
->data
, &child_allocation
);
550 child_allocation
.x
+= child_allocation
.width
;
552 child_allocation
.x
+= ASCII_BORDER
;
555 child_allocation
.width
= view
->bytes_by_line
* ascii_requisition
.width
;
556 gtk_widget_size_allocate (view
->ascii
, &child_allocation
);
557 child_allocation
.x
+= child_allocation
.width
;
561 gdouble page_increment
, page_size
, upper
;
563 page_increment
= view
->bytes_by_line
* (view
->line_by_page
- 1);
564 upper
= gtk_adjustment_get_upper (view
->buffer_range
);
565 page_size
= (gulong
) upper
% view
->bytes_by_line
+ page_increment
;
567 gtk_adjustment_set_step_increment (view
->buffer_range
, view
->bytes_by_line
);
568 gtk_adjustment_set_page_increment (view
->buffer_range
, page_increment
);
569 gtk_adjustment_set_page_size (view
->buffer_range
, page_size
);
571 if (view
->start
+ page_size
> upper
)
573 view
->start
= upper
- page_size
+ view
->bytes_by_line
- 1;
574 view
->start
-= view
->start
% view
->bytes_by_line
;
576 dma_data_view_refresh (view
);
582 dma_data_view_paint (GtkWidget
*widget
,
585 gtk_render_frame (gtk_widget_get_style_context (widget
), cr
, 0, 0,
586 gtk_widget_get_allocated_width (widget
),
587 gtk_widget_get_allocated_height (widget
));
591 dma_data_view_draw (GtkWidget
*widget
,
594 dma_data_view_paint (widget
, cr
);
596 (* GTK_WIDGET_CLASS (dma_data_view_parent_class
)->draw
) (widget
, cr
);
601 dma_data_view_changed_notify (DmaDataBuffer
* buffer
, gulong lower
, gulong upper
, DmaDataView
*view
)
603 if ((upper
>= view
->start
) && (lower
< (view
->start
+ view
->line_by_page
* view
->bytes_by_line
)))
605 dma_data_view_refresh (view
);
610 *---------------------------------------------------------------------------*/
613 dma_data_view_goto_address (DmaDataView
*view
, const void *address
)
615 gtk_adjustment_set_value (view
->view_range
, (gdouble
)((gulong
)address
));
619 dma_data_view_get_address (DmaDataView
*view
)
621 return view
->address
;
625 dma_data_view_get_data (DmaDataView
*view
)
631 dma_data_view_get_ascii (DmaDataView
*view
)
637 dma_data_view_refresh (DmaDataView
*view
)
643 GtkTextBuffer
*buffer
;
645 /* Save all cursor offset */
646 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (view
->address
));
647 mark
= gtk_text_buffer_get_insert (buffer
);
648 gtk_text_buffer_get_iter_at_mark (buffer
, &cur
, mark
);
649 offset
= gtk_text_iter_get_offset (&cur
);
651 data
= dma_data_buffer_get_address (view
->buffer
, view
->start
, view
->line_by_page
* view
->bytes_by_line
, view
->bytes_by_line
, sizeof(view
->start
) * 2);
652 gtk_text_buffer_set_text (buffer
, data
, -1);
655 mark
= gtk_text_buffer_get_insert (buffer
);
656 gtk_text_buffer_get_iter_at_mark (buffer
, &cur
, mark
);
657 gtk_text_iter_set_offset (&cur
, offset
);
658 gtk_text_buffer_move_mark_by_name (buffer
, "insert", &cur
);
659 gtk_text_buffer_move_mark_by_name (buffer
, "selection_bound", &cur
);
662 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (view
->data
));
663 mark
= gtk_text_buffer_get_insert (buffer
);
664 gtk_text_buffer_get_iter_at_mark (buffer
, &cur
, mark
);
665 offset
= gtk_text_iter_get_offset (&cur
);
667 data
= dma_data_buffer_get_data (view
->buffer
, view
->start
, view
->line_by_page
* view
->bytes_by_line
, view
->bytes_by_line
, DMA_HEXADECIMAL_BASE
);
668 gtk_text_buffer_set_text (buffer
, data
, -1);
671 mark
= gtk_text_buffer_get_insert (buffer
);
672 gtk_text_buffer_get_iter_at_mark (buffer
, &cur
, mark
);
673 gtk_text_iter_set_offset (&cur
, offset
);
674 gtk_text_buffer_move_mark_by_name (buffer
, "insert", &cur
);
675 gtk_text_buffer_move_mark_by_name (buffer
, "selection_bound", &cur
);
678 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (view
->ascii
));
679 mark
= gtk_text_buffer_get_insert (buffer
);
680 gtk_text_buffer_get_iter_at_mark (buffer
, &cur
, mark
);
681 offset
= gtk_text_iter_get_offset (&cur
);
683 data
= dma_data_buffer_get_data (view
->buffer
, view
->start
, view
->line_by_page
* view
->bytes_by_line
, view
->bytes_by_line
, DMA_ASCII_BASE
);
684 gtk_text_buffer_set_text (buffer
, data
, -1);
687 mark
= gtk_text_buffer_get_insert (buffer
);
688 gtk_text_buffer_get_iter_at_mark (buffer
, &cur
, mark
);
689 gtk_text_iter_set_offset (&cur
, offset
);
690 gtk_text_buffer_move_mark_by_name (buffer
, "insert", &cur
);
691 gtk_text_buffer_move_mark_by_name (buffer
, "selection_bound", &cur
);
695 /* GtkContainer functions
696 *---------------------------------------------------------------------------*/
699 dma_data_view_child_type (GtkContainer
*container
)
705 dma_data_view_forall (GtkContainer
*container
,
706 gboolean include_internals
,
707 GtkCallback callback
,
708 gpointer callback_data
)
710 DmaDataView
*view
= DMA_DATA_VIEW (container
);
712 g_return_if_fail (callback
!= NULL
);
714 if (include_internals
)
716 callback (view
->address
, callback_data
);
717 callback (view
->data
, callback_data
);
718 callback (view
->ascii
, callback_data
);
719 callback (view
->range
, callback_data
);
724 /* GtkObject functions
725 *---------------------------------------------------------------------------*/
728 dma_data_view_destroy (GtkWidget
*object
)
732 g_return_if_fail (IS_DMA_DATA_VIEW (object
));
734 view
= DMA_DATA_VIEW (object
);
736 gtk_widget_unparent (view
->address
);
737 gtk_widget_destroy (view
->address
);
738 gtk_widget_unparent (view
->data
);
739 gtk_widget_destroy (view
->data
);
740 gtk_widget_unparent (view
->ascii
);
741 gtk_widget_destroy (view
->ascii
);
742 gtk_widget_unparent (view
->range
);
743 gtk_widget_destroy (view
->range
);
745 if (view
->goto_window
)
747 gtk_widget_destroy (view
->goto_window
);
748 view
->goto_window
= NULL
;
749 view
->goto_entry
= NULL
;
752 GTK_WIDGET_CLASS (dma_data_view_parent_class
)->destroy (object
);
757 *---------------------------------------------------------------------------*/
759 /* dispose is the first destruction step. It is used to unref object created
760 * with instance_init in order to break reference counting cycles. This
761 * function could be called several times. All function should still work
762 * after this call. It has to called its parents.*/
765 dma_data_view_dispose (GObject
*object
)
767 DmaDataView
*view
= DMA_DATA_VIEW (object
);
769 if (view
->buffer
!= NULL
)
771 g_signal_handlers_disconnect_by_func (view
->buffer
,
772 dma_data_view_changed_notify
,
774 g_object_unref (view
->buffer
);
778 G_OBJECT_CLASS (dma_data_view_parent_class
)->dispose (object
);
781 /* finalize is the last destruction step. It must free all memory allocated
782 * with instance_init. It is called only one time just before releasing all
786 dma_data_view_finalize (GObject
*object
)
788 DmaDataView
*view
= DMA_DATA_VIEW (object
);
790 g_object_unref (view
->address
);
791 g_object_unref (view
->data
);
792 g_object_unref (view
->ascii
);
793 g_object_unref (view
->range
);
795 G_OBJECT_CLASS (dma_data_view_parent_class
)->finalize (object
);
799 dma_data_view_constructed (GObject
*object
)
801 DmaDataView
*view
= DMA_DATA_VIEW (object
);
804 g_signal_connect (G_OBJECT (view
->buffer
),
806 G_CALLBACK (dma_data_view_changed_notify
),
809 wid
= GTK_WIDGET (view
);
811 gtk_widget_set_has_window (wid
, FALSE
);
812 gtk_widget_set_can_focus (wid
, TRUE
);
813 gtk_widget_set_redraw_on_allocate (wid
, FALSE
);
815 view
->char_by_byte
= 2;
816 view
->bytes_by_line
= 16;
817 view
->line_by_page
= 16;
819 view
->hadjustment
= NULL
;
820 view
->vadjustment
= NULL
;
822 view
->goto_window
= NULL
;
823 view
->goto_entry
= NULL
;
825 view
->buffer_range
= GTK_ADJUSTMENT (gtk_adjustment_new (0,
826 dma_data_buffer_get_lower (view
->buffer
),
827 dma_data_buffer_get_upper (view
->buffer
)
829 g_signal_connect (view
->buffer_range
, "value_changed",
830 G_CALLBACK (dma_data_view_value_changed
), view
);
832 wid
= gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL
, view
->buffer_range
);
835 gtk_widget_set_parent (wid
, GTK_WIDGET (view
));
836 gtk_widget_show (wid
);
838 wid
= dma_chunk_view_new ();
840 gtk_widget_set_parent (wid
, GTK_WIDGET (view
));
841 gtk_widget_set_size_request (wid
, -1, 0);
842 gtk_widget_show (wid
);
843 gtk_text_view_set_editable (GTK_TEXT_VIEW (wid
), FALSE
);
845 view
->ascii_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (wid
));
846 dma_chunk_view_set_scroll_adjustment (DMA_CHUNK_VIEW (wid
), view
->buffer_range
);
847 g_signal_connect (wid
, "populate_popup",
848 G_CALLBACK (dma_data_view_populate_popup
), view
);
850 wid
= dma_chunk_view_new ();
852 gtk_widget_set_parent (wid
, GTK_WIDGET (view
));
853 gtk_widget_set_size_request (wid
, -1, 0);
854 gtk_widget_show (wid
);
855 gtk_text_view_set_editable (GTK_TEXT_VIEW (wid
), FALSE
);
857 view
->data_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (wid
));
858 dma_chunk_view_set_scroll_adjustment (DMA_CHUNK_VIEW (wid
), view
->buffer_range
);
859 g_signal_connect (wid
, "populate_popup",
860 G_CALLBACK (dma_data_view_populate_popup
), view
);
862 wid
= dma_chunk_view_new ();
864 gtk_widget_set_parent (wid
, GTK_WIDGET (view
));
865 gtk_widget_set_size_request (wid
, -1, 0);
866 gtk_widget_show (wid
);
867 gtk_text_view_set_editable (GTK_TEXT_VIEW (wid
), FALSE
);
869 view
->adr_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (wid
));
870 dma_chunk_view_set_scroll_adjustment (DMA_CHUNK_VIEW (wid
), view
->buffer_range
);
871 g_signal_connect (wid
, "populate_popup",
872 G_CALLBACK (dma_data_view_populate_popup
), view
);
876 dma_data_view_set_property (GObject
*object
, guint prop_id
,
877 const GValue
*value
, GParamSpec
*pspec
)
879 DmaDataView
*view
= DMA_DATA_VIEW (object
);
884 view
->buffer
= g_value_dup_object (value
);
888 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
893 dma_data_view_get_property (GObject
*object
, guint prop_id
,
894 GValue
*value
, GParamSpec
*pspec
)
896 DmaDataView
*view
= DMA_DATA_VIEW (object
);
901 g_value_set_object (value
, view
->buffer
);
905 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
910 dma_data_view_init (DmaDataView
*view
)
912 GtkStyleContext
*context
;
915 context
= gtk_widget_get_style_context (GTK_WIDGET (view
));
916 gtk_style_context_add_provider (context
,
917 GTK_STYLE_PROVIDER (GET_DMA_DATA_VIEW_CLASS (view
)->css
),
918 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
920 gtk_widget_set_has_window (GTK_WIDGET (view
), FALSE
);
923 /* class_init intialize the class itself not the instance */
926 dma_data_view_class_init (DmaDataViewClass
* klass
)
928 GObjectClass
*gobject_class
;
929 GtkWidgetClass
*widget_class
;
930 GtkContainerClass
*container_class
;
932 static const gchar data_view_style
[] =
934 " font: Monospace 10;\n"
937 gobject_class
= G_OBJECT_CLASS (klass
);
938 widget_class
= GTK_WIDGET_CLASS (klass
);
939 container_class
= GTK_CONTAINER_CLASS (klass
);
941 gobject_class
->set_property
= dma_data_view_set_property
;
942 gobject_class
->get_property
= dma_data_view_get_property
;
943 gobject_class
->constructed
= dma_data_view_constructed
;
944 gobject_class
->dispose
= dma_data_view_dispose
;
945 gobject_class
->finalize
= dma_data_view_finalize
;
947 widget_class
->destroy
= dma_data_view_destroy
;
948 widget_class
->get_preferred_width
= dma_data_view_get_preferred_width
;
949 widget_class
->get_preferred_height
= dma_data_view_get_preferred_height
;
950 widget_class
->size_allocate
= dma_data_view_size_allocate
;
951 widget_class
->draw
= dma_data_view_draw
;
953 container_class
->forall
= dma_data_view_forall
;
954 container_class
->child_type
= dma_data_view_child_type
;
956 properties
[PROP_BUFFER
] =
957 g_param_spec_object ("buffer", "Buffer", "Buffer",
958 DMA_DATA_BUFFER_TYPE
,
959 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
);
960 g_object_class_install_properties (gobject_class
, N_PROPERTIES
, properties
);
962 klass
->css
= gtk_css_provider_new ();
963 gtk_css_provider_load_from_data (klass
->css
, data_view_style
, -1, NULL
);
966 /* Creation and Destruction
967 *---------------------------------------------------------------------------*/
970 dma_data_view_new_with_buffer (DmaDataBuffer
* buffer
)
974 view
= g_object_new (DMA_DATA_VIEW_TYPE
, "buffer", buffer
, NULL
);
975 return GTK_WIDGET (view
);