Updated Makefile.am files after make -f git.mk
[anjuta.git] / plugins / debug-manager / data_view.c
blobf391c2e95ce40c3bbbffe307dfbe27af8d69cd35
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 data_view.c
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>
31 #include <stdlib.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
38 struct _DmaDataView
40 GtkContainer parent;
42 GtkWidget *address;
43 GtkWidget *data;
44 GtkWidget *ascii;
45 GtkWidget *range;
47 GtkWidget *goto_window;
48 GtkWidget *goto_entry;
50 guint16 shadow_type;
51 GtkAllocation frame;
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;
65 gulong start;
67 guint bytes_by_line;
68 guint line_by_page;
69 guint char_by_byte;
70 guint char_height;
71 guint char_width;
74 struct _DmaDataViewClass
76 GtkContainerClass parent_class;
78 GtkCssProvider *css;
81 enum {
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);
88 /* Helper functions
89 *---------------------------------------------------------------------------*/
91 #if 0
92 static void
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,*/
104 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);
113 #endif
115 static void
116 get_css_padding_and_border (GtkWidget *widget,
117 GtkBorder *border)
119 GtkStyleContext *context;
120 GtkStateFlags state;
121 GtkBorder tmp;
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 *---------------------------------------------------------------------------*/
137 static void
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), "");
144 static gboolean
145 dma_data_view_goto_delete_event (GtkWidget *widget,
146 GdkEventAny *event,
147 DmaDataView *view)
149 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
151 dma_data_view_goto_window_hide (view);
153 return TRUE;
156 static gboolean
157 dma_data_view_goto_key_press_event (GtkWidget *widget,
158 GdkEventKey *event,
159 DmaDataView *view)
161 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
162 g_return_val_if_fail (IS_DMA_DATA_VIEW (view), FALSE);
164 /* Close window */
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);
171 return TRUE;
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)
179 gulong adr;
180 const gchar *text;
181 gchar *end;
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);
193 return TRUE;
196 return FALSE;
199 static void
200 dma_data_view_goto_position_func (DmaDataView *view)
202 gint x, y;
203 gint win_x, win_y;
204 GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (view));
205 GdkScreen *screen = gdk_window_get_screen (window);
206 gint monitor_num;
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 */
222 static void
223 send_focus_change (GtkWidget *widget,
224 gboolean in)
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);
236 static void
237 dma_data_view_goto_activate (GtkWidget *menu_item,
238 DmaDataView *view)
240 GtkWidget *toplevel;
241 GtkWidget *frame;
242 GtkWidget *vbox;
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)
252 if (toplevel_group)
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));
260 else
262 view->goto_window = gtk_window_new (GTK_WINDOW_POPUP);
264 if (toplevel_group)
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),
271 view);
272 g_signal_connect (view->goto_window, "key_press_event",
273 G_CALLBACK (dma_data_view_goto_key_press_event),
274 view);
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);
286 /* add entry */
287 view->goto_entry = gtk_entry_new ();
288 gtk_entry_set_icon_from_stock (GTK_ENTRY (view->goto_entry),
289 GTK_ENTRY_ICON_PRIMARY,
290 GTK_STOCK_JUMP_TO);
291 gtk_widget_show (view->goto_entry);
292 gtk_container_add (GTK_CONTAINER (vbox),
293 view->goto_entry);
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);
308 /* Private functions
309 *---------------------------------------------------------------------------*/
311 static void
312 dma_data_view_address_size_request (DmaDataView *view,
313 GtkRequisition *requisition)
315 PangoLayout *layout;
316 char text[] = "0";
317 int width;
318 int height;
320 layout = gtk_widget_create_pango_layout(view->address, text);
321 pango_layout_get_pixel_size(layout, &(requisition->width), &(requisition->height));
324 text[0]++;
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;
340 static void
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);
361 static void
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);
383 static void
384 dma_data_view_value_changed (GtkAdjustment *adj,
385 DmaDataView *view)
387 gdouble value;
389 value = gtk_adjustment_get_value (adj);
390 view->start = ((gulong) value) - (((gulong) value) % view->bytes_by_line);
391 dma_data_view_refresh (view);
394 static void
395 dma_data_view_populate_popup (GtkTextView *widget,
396 GtkMenu *menu,
397 DmaDataView *view)
399 GtkWidget *menu_item;
401 /* separator */
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);
414 static void
415 dma_data_view_get_preferred_width (GtkWidget *widget,
416 gint *minimum_width, gint *natural_width)
418 DmaDataView *view = DMA_DATA_VIEW (widget);
419 gint width;
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;
444 static void
445 dma_data_view_get_preferred_height (GtkWidget *widget,
446 gint *minimum_height, gint *natural_height)
448 DmaDataView *view = DMA_DATA_VIEW (widget);
449 gint height;
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;
470 static void
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;
481 gint width;
482 gint height;
483 gint bytes_by_line;
484 gint step;
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)
498 - ADDRESS_BORDER
499 - ASCII_BORDER
500 - SCROLLBAR_SPACING
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)
514 need_fill = TRUE;
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))
523 need_fill = TRUE;
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));
531 /* Scroll bar */
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;
539 /* Address */
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;
546 /* Data */
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;
554 /* Ascii */
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;
559 if (need_fill)
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);
581 static void
582 dma_data_view_paint (GtkWidget *widget,
583 cairo_t *cr)
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));
590 static gint
591 dma_data_view_draw (GtkWidget *widget,
592 cairo_t *cr)
594 dma_data_view_paint (widget, cr);
596 (* GTK_WIDGET_CLASS (dma_data_view_parent_class)->draw) (widget, cr);
597 return FALSE;
600 static void
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);
609 /* Public functions
610 *---------------------------------------------------------------------------*/
612 void
613 dma_data_view_goto_address (DmaDataView *view, const void *address)
615 gtk_adjustment_set_value (view->view_range, (gdouble)((gulong)address));
618 GtkWidget *
619 dma_data_view_get_address (DmaDataView *view)
621 return view->address;
624 GtkWidget *
625 dma_data_view_get_data (DmaDataView *view)
627 return view->data;
630 GtkWidget *
631 dma_data_view_get_ascii (DmaDataView *view)
633 return view->ascii;
636 void
637 dma_data_view_refresh (DmaDataView *view)
639 gchar *data = "";
640 gint offset;
641 GtkTextIter cur;
642 GtkTextMark *mark;
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);
653 g_free (data);
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);
669 g_free (data);
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);
685 g_free (data);
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 *---------------------------------------------------------------------------*/
698 static GType
699 dma_data_view_child_type (GtkContainer *container)
701 return G_TYPE_NONE;
704 static void
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 *---------------------------------------------------------------------------*/
727 static void
728 dma_data_view_destroy (GtkWidget *object)
730 DmaDataView *view;
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);
756 /* GObject functions
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.*/
764 static void
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,
773 view);
774 g_object_unref (view->buffer);
775 view->buffer = NULL;
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
783 * memory */
785 static void
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);
798 static void
799 dma_data_view_constructed (GObject *object)
801 DmaDataView *view = DMA_DATA_VIEW (object);
802 GtkWidget* wid;
804 g_signal_connect (G_OBJECT (view->buffer),
805 "changed_notify",
806 G_CALLBACK (dma_data_view_changed_notify),
807 view);
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)
828 ,1,4,4));
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);
833 g_object_ref (wid);
834 view->range = wid;
835 gtk_widget_set_parent (wid, GTK_WIDGET (view));
836 gtk_widget_show (wid);
838 wid = dma_chunk_view_new ();
839 g_object_ref (wid);
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);
844 view->ascii = wid;
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 ();
851 g_object_ref (wid);
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);
856 view->data = wid;
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 ();
863 g_object_ref (wid);
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);
868 view->address = wid;
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);
875 static void
876 dma_data_view_set_property (GObject *object, guint prop_id,
877 const GValue *value, GParamSpec *pspec)
879 DmaDataView *view = DMA_DATA_VIEW (object);
881 switch (prop_id)
883 case PROP_BUFFER:
884 view->buffer = g_value_dup_object (value);
885 break;
887 default:
888 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
892 static void
893 dma_data_view_get_property (GObject *object, guint prop_id,
894 GValue *value, GParamSpec *pspec)
896 DmaDataView *view = DMA_DATA_VIEW (object);
898 switch (prop_id)
900 case PROP_BUFFER:
901 g_value_set_object (value, view->buffer);
902 break;
904 default:
905 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
909 static void
910 dma_data_view_init (DmaDataView *view)
912 GtkStyleContext *context;
914 /* Setup styling */
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 */
925 static void
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[] =
933 "* {\n"
934 " font: Monospace 10;\n"
935 "}";
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 *---------------------------------------------------------------------------*/
969 GtkWidget*
970 dma_data_view_new_with_buffer (DmaDataBuffer* buffer)
972 DmaDataView *view;
974 view = g_object_new (DMA_DATA_VIEW_TYPE, "buffer", buffer, NULL);
975 return GTK_WIDGET (view);