summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-12-20 22:12:28 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-12-20 22:12:28 (GMT)
commitcffbe4839da452af215f05dfb7cc6c9304c1285e (patch)
treed2ea78b67592e868ed94ab189722670379cd2b67
parent0f58e137ff493ab38d2a7e6e2d5e5bc85951be3d (diff)
Kept the current location when switching views.
-rw-r--r--src/glibext/gbufferview.c9
-rw-r--r--src/glibext/linesegment.c53
-rw-r--r--src/glibext/linesegment.h6
-rw-r--r--src/gtkext/graph/cluster.c25
-rw-r--r--src/gtkext/graph/cluster.h3
-rw-r--r--src/gtkext/gtkbufferdisplay.c56
-rw-r--r--src/gtkext/gtkbufferdisplay.h3
-rw-r--r--src/gtkext/gtkdisplaypanel.c31
-rw-r--r--src/gtkext/gtkdisplaypanel.h4
-rw-r--r--src/gtkext/gtkgraphdisplay.c58
-rw-r--r--src/gui/menus/view.c57
11 files changed, 290 insertions, 15 deletions
diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c
index f5adc9d..2239d23 100644
--- a/src/glibext/gbufferview.c
+++ b/src/glibext/gbufferview.c
@@ -36,7 +36,6 @@ struct _GBufferView
GBufferCache *cache; /* Tampon du contenu visualisé */
segcnt_list *highlighted; /* Segments mis en évidence */
- bool external; /* Note l'origine de la liste */
bool unrestricted; /* Validité des informations */
GLineCursor *start; /* Première ligne intégrée */
@@ -189,8 +188,7 @@ static void g_buffer_view_dispose(GBufferView *view)
static void g_buffer_view_finalize(GBufferView *view)
{
- if (!view->external)
- exit_segment_content_list(view->highlighted);
+ unref_segment_content_list(view->highlighted);
G_OBJECT_CLASS(g_buffer_view_parent_class)->finalize(G_OBJECT(view));
@@ -223,12 +221,13 @@ GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted)
g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result);
if (highlighted != NULL)
+ {
+ ref_segment_content_list(highlighted);
result->highlighted = highlighted;
+ }
else
result->highlighted = init_segment_content_list();
- result->external = (highlighted != NULL);
-
return result;
}
diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c
index 557dff2..15fde78 100644
--- a/src/glibext/linesegment.c
+++ b/src/glibext/linesegment.c
@@ -148,6 +148,8 @@ struct _segcnt_list
fnv64_t *hashes; /* Empreinte pour comparaisons */
size_t count; /* Nommbre de ces empreintes */
+ unsigned int ref_count; /* Compteur de références */
+
};
@@ -970,7 +972,12 @@ segcnt_list *init_segment_content_list(void)
{
segcnt_list *result; /* Structure à retourner */
- result = (segcnt_list *)calloc(1, sizeof(segcnt_list));
+ result = malloc(sizeof(segcnt_list));
+
+ result->hashes = NULL;
+ result->count = 0;
+
+ result->ref_count = 1;
return result;
@@ -991,6 +998,8 @@ segcnt_list *init_segment_content_list(void)
void exit_segment_content_list(segcnt_list *list)
{
+ assert(list->ref_count == 0);
+
reset_segment_content_list(list);
free(list);
@@ -1000,6 +1009,48 @@ void exit_segment_content_list(segcnt_list *list)
/******************************************************************************
* *
+* Paramètres : list = ensemble de références de contenus à traiter. *
+* *
+* Description : Incrémente le nombre d'utilisation de la liste de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void ref_segment_content_list(segcnt_list *list)
+{
+ assert(list->ref_count > 0);
+
+ list->ref_count++;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de références de contenus à traiter. *
+* *
+* Description : Décrémente le nombre d'utilisation de la liste de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unref_segment_content_list(segcnt_list *list)
+{
+ assert(list->ref_count > 0);
+
+ list->ref_count--;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : list = ensemble de références de contenus à manipuler. *
* *
* Description : Vide, si besoin est, une liste de contenus de segments. *
diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h
index c6deb38..9723a80 100644
--- a/src/glibext/linesegment.h
+++ b/src/glibext/linesegment.h
@@ -191,6 +191,12 @@ segcnt_list *init_segment_content_list(void);
/* Libère la mémoire occupée par une liste de contenus. */
void exit_segment_content_list(segcnt_list *);
+/* Incrémente le nombre d'utilisation de la liste de contenus. */
+void ref_segment_content_list(segcnt_list *);
+
+/* Décrémente le nombre d'utilisation de la liste de contenus. */
+void unref_segment_content_list(segcnt_list *);
+
/* Vide, si besoin est, une liste de contenus de segments. */
bool reset_segment_content_list(segcnt_list *);
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
index 9bbfb34..17af9ce 100644
--- a/src/gtkext/graph/cluster.c
+++ b/src/gtkext/graph/cluster.c
@@ -790,6 +790,31 @@ void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAlloc
/******************************************************************************
* *
+* Paramètres : cluster = encapsulation à consulter. *
+* *
+* Description : Fournit le composant graphique principal du groupe. *
+* *
+* Retour : Composant graphique principal utilisé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *g_graph_cluster_get_widget(GGraphCluster *cluster)
+{
+ GtkWidget *result;
+
+ result = cluster->display;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : cluster = encapsulation à traiter. *
* display = support de destination finale. *
* *
diff --git a/src/gtkext/graph/cluster.h b/src/gtkext/graph/cluster.h
index fbf2d10..11ce66e 100644
--- a/src/gtkext/graph/cluster.h
+++ b/src/gtkext/graph/cluster.h
@@ -56,6 +56,9 @@ GGraphCluster *g_graph_cluster_new(GCodeBlock *, segcnt_list *, GLoadedBinary *)
/* Détermine l'emplacement requis d'un ensemble de blocs. */
void g_graph_cluster_compute_needed_alloc(const GGraphCluster *, GtkAllocation *);
+/* Fournit le composant graphique principal du groupe. */
+GtkWidget *g_graph_cluster_get_widget(GGraphCluster *);
+
/* Dispose chaque noeud sur la surface de destination donnée. */
void g_graph_cluster_place(GGraphCluster *, GtkGraphDisplay *);
diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c
index 1989b1c..a748cf2 100644
--- a/src/gtkext/gtkbufferdisplay.c
+++ b/src/gtkext/gtkbufferdisplay.c
@@ -212,6 +212,12 @@ static void gtk_buffer_display_init(GtkBufferDisplay *display)
static void gtk_buffer_display_dispose(GtkBufferDisplay *display)
{
+ if (display->caret_timer != 0)
+ {
+ g_source_remove(display->caret_timer);
+ display->caret_timer = 0;
+ }
+
g_clear_object(&display->view);
g_clear_object(&display->cursor);
@@ -814,6 +820,56 @@ GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *display)
/******************************************************************************
* *
+* Paramètres : display = composant GTK à consulter. *
+* cursor = définition générique d'une localisation à l'écran. *
+* *
+* Description : Détermine si une position est comprise dans l'affichage. *
+* *
+* Retour : true si le composant comprend bien la localisation fournie. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_buffer_display_contains_cursor(const GtkBufferDisplay *display, const GLineCursor *cursor)
+{
+ bool result; /* Bilan à retourner */
+ GLineCursor *start; /* Position initiale du tampon */
+ GLineCursor *end; /* Position finale du tampon */
+ int status; /* Bilan d'une comparaison */
+
+ g_buffer_view_get_restrictions(display->view, &start, &end);
+
+ if (start == NULL && end == NULL)
+ result = NULL;
+
+ else
+ {
+ status = g_line_cursor_compare(start, cursor);
+
+ if (status > 0)
+ result = false;
+
+ else
+ {
+ status = g_line_cursor_compare(cursor, end);
+
+ result = (status < 0);
+
+ }
+
+ g_object_unref(G_OBJECT(start));
+ g_object_unref(G_OBJECT(end));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : display = composant GTK à manipuler. *
* x = abscisse proposée pour le nouvel emplacement. *
* y = ordonnée proposée pour le nouvel emplacement. *
diff --git a/src/gtkext/gtkbufferdisplay.h b/src/gtkext/gtkbufferdisplay.h
index dc2e4ff..73fbbde 100644
--- a/src/gtkext/gtkbufferdisplay.h
+++ b/src/gtkext/gtkbufferdisplay.h
@@ -59,6 +59,9 @@ GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *);
/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */
+/* Détermine si une position est comprise dans l'affichage. */
+bool gtk_buffer_display_contains_cursor(const GtkBufferDisplay *, const GLineCursor *);
+
/* Déplace le curseur à un emplacement en extrémité. */
bool gtk_buffer_display_move_caret_to(GtkBufferDisplay *, bool, gint *);
diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c
index 3623ced..93e47e7 100644
--- a/src/gtkext/gtkdisplaypanel.c
+++ b/src/gtkext/gtkdisplaypanel.c
@@ -887,6 +887,33 @@ const vmpa2t *gtk_display_panel_get_caret_location(const GtkDisplayPanel *panel)
/******************************************************************************
* *
+* Paramètres : panel = composant GTK à consulter. *
+* cursor = emplacement à présenter à l'écran. *
+* x = position horizontale au sein du composant. [OUT] *
+* y = position verticale au sein du composant. [OUT] *
+* tweak = adaptation finale à effectuer. *
+* *
+* Description : Indique la position d'affichage d'un emplacement donné. *
+* *
+* Retour : true si l'adresse fait partie du composant, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_display_panel_get_cursor_coordinates(const GtkDisplayPanel *panel, const GLineCursor *cursor, gint *x, gint *y, ScrollPositionTweak tweak)
+{
+ bool result; /* Bilan à remonter */
+
+ result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_coordinates(panel, cursor, x, y, tweak);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : panel = composant GTK à consulter. *
* *
* Description : Fournit l'élément actif lié à la position courante. *
@@ -1182,7 +1209,7 @@ static void gtk_display_panel_scroll_to_cursor(GtkDisplayPanel *panel, const GLi
GTK_DISPLAY_PANEL_GET_CLASS(panel)->define(panel, addr);
*/
- if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_coordinates(panel, cursor, &x, &y, tweak))
+ if (gtk_display_panel_get_cursor_coordinates(panel, cursor, &x, &y, tweak))
{
viewport = gtk_widget_get_parent(GTK_WIDGET(panel));
@@ -1216,7 +1243,7 @@ static void gtk_display_panel_scroll_to_cursor(GtkDisplayPanel *panel, const GLi
/* Déplacement du curseur */
- if (move && GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_coordinates(panel, cursor, &x, &y, SPT_RAW))
+ if (move && gtk_display_panel_get_cursor_coordinates(panel, cursor, &x, &y, SPT_RAW))
GTK_DISPLAY_PANEL_GET_CLASS(panel)->move_caret_to(panel, x, y);
}
diff --git a/src/gtkext/gtkdisplaypanel.h b/src/gtkext/gtkdisplaypanel.h
index 51648df..6baac64 100644
--- a/src/gtkext/gtkdisplaypanel.h
+++ b/src/gtkext/gtkdisplaypanel.h
@@ -30,6 +30,7 @@
#include "../arch/vmpa.h"
+#include "../glibext/gloadedpanel.h"
@@ -63,6 +64,9 @@ void gtk_display_panel_set_code_display(GtkDisplayPanel *, bool);
/* Indique la position courante du curseur. */
const vmpa2t *gtk_display_panel_get_caret_location(const GtkDisplayPanel *);
+/* Indique la position d'affichage d'un emplacement donné. */
+bool gtk_display_panel_get_cursor_coordinates(const GtkDisplayPanel *, const GLineCursor *, gint *, gint *, ScrollPositionTweak);
+
/* Fournit l'élément actif lié à la position courante. */
GObject *gtk_display_panel_get_active_object(const GtkDisplayPanel *);
diff --git a/src/gtkext/gtkgraphdisplay.c b/src/gtkext/gtkgraphdisplay.c
index 955f540..6187677 100644
--- a/src/gtkext/gtkgraphdisplay.c
+++ b/src/gtkext/gtkgraphdisplay.c
@@ -637,6 +637,7 @@ static void gtk_graph_display_define_main_address(GtkGraphDisplay *display, cons
gint right; /* Abscisse du coin droit */
gint bottom; /* Ordonnée du coin inférieur */
GtkAllocation allocation; /* Espace alloué au panneau */
+ GtkWidget *child; /* Composant sélectionné */
if (display->routine == NULL)
need_update = true;
@@ -694,6 +695,16 @@ static void gtk_graph_display_define_main_address(GtkGraphDisplay *display, cons
gtk_graph_display_update_support_margins(display, &allocation);
+ /**
+ * Première sélection...
+ */
+
+ child = g_graph_cluster_get_widget(display->cluster);
+
+ gtk_container_set_focus_child(GTK_CONTAINER(display->support), child);
+
+ g_object_unref(G_OBJECT(child));
+
ggddma_bad_type:
g_object_unref(G_OBJECT(symbol));
@@ -746,9 +757,42 @@ static const vmpa2t *gtk_graph_display_get_caret_location(const GtkGraphDisplay
static bool gtk_graph_display_get_cursor_coordinates(const GtkGraphDisplay *display, const GLineCursor *cursor, gint *x, gint *y, ScrollPositionTweak tweak)
{
- /* TODO */
+ bool result; /* Bilan final à retourner */
+ GList *children; /* Sous-composants à parcourir */
+ GList *iter; /* Boucle de parcours */
+ GtkWidget *child; /* Composant embarqué */
+ GtkAllocation alloc; /* Emplacement réservé */
+
+ result = false;
+
+ children = gtk_container_get_children(GTK_CONTAINER(display->support));
- return false;
+ for (iter = g_list_first(children); iter != NULL; iter = g_list_next(iter))
+ {
+ child = GTK_WIDGET(iter->data);
+
+ if (!GTK_IS_BUFFER_DISPLAY(child))
+ continue;
+
+ result = gtk_buffer_display_contains_cursor(GTK_BUFFER_DISPLAY(child), cursor);
+
+ if (result)
+ {
+ result = gtk_display_panel_get_cursor_coordinates(GTK_DISPLAY_PANEL(child), cursor, x, y, tweak);
+ assert(result);
+
+ gtk_widget_get_allocation(child, &alloc);
+
+ *x += alloc.x;
+ *y += alloc.y;
+ break;
+ }
+
+ }
+
+ g_list_free(children);
+
+ return result;
}
@@ -822,8 +866,14 @@ static bool gtk_graph_display_move_caret_to(GtkGraphDisplay *display, gint x, gi
static GLineCursor *gtk_graph_display_get_cursor(const GtkGraphDisplay *display)
{
GLineCursor *result; /* Contenu à retourner */
+ GtkWidget *child; /* Composant sélectionné */
+
+ child = gtk_container_get_focus_child(GTK_CONTAINER(display->support));
- result = NULL;
+ if (child != NULL)
+ result = g_loaded_panel_get_cursor(G_LOADED_PANEL(child));
+ else
+ result = NULL;
return result;
@@ -1012,7 +1062,7 @@ static void gtk_graph_display_reset(GtkGraphDisplay *display, bool dispose)
if (display->highlighted != NULL)
{
- exit_segment_content_list(display->highlighted);
+ unref_segment_content_list(display->highlighted);
display->highlighted = NULL;
}
diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c
index 4591c0f..63b6371 100644
--- a/src/gui/menus/view.c
+++ b/src/gui/menus/view.c
@@ -58,6 +58,9 @@ static void mcb_view_switch_to_next_support(GtkRadioMenuItem *, gpointer);
/* Réagit avec le menu "Affichage -> Basculer vers le précédent". */
static void mcb_view_switch_to_prev_support(GtkRadioMenuItem *, gpointer);
+/* Accompagne la première allocation d'un panneau d'affichage. */
+static void handle_loaded_panel_first_allocation(GtkWidget *, GdkRectangle *, GLineCursor *);
+
/* Effectue la bascule d'un panneau de chargement à un autre. */
static void change_current_view_support(unsigned int);
@@ -741,6 +744,32 @@ static void mcb_view_switch_to_prev_support(GtkRadioMenuItem *menuitem, gpointer
/******************************************************************************
* *
+* Paramètres : widget = composant graphique visé par la procédure. *
+* alloc = emplacement accordé à ce composant. *
+* cursor = emplacement transmis à présenter en premier lieu. *
+* *
+* Description : Accompagne la première allocation d'un panneau d'affichage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void handle_loaded_panel_first_allocation(GtkWidget *widget, GdkRectangle *alloc, GLineCursor *cursor)
+{
+ /* On ne réagit que la première fois */
+ g_signal_handlers_disconnect_by_func(widget, G_CALLBACK(handle_loaded_panel_first_allocation), cursor);
+
+ g_loaded_panel_scroll_to_cursor(G_LOADED_PANEL(widget), cursor, SPT_TOP, true);
+
+ g_object_unref(G_OBJECT(cursor));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : wanted = indice de la vue désirée. *
* *
* Description : Effectue la bascule d'un panneau de chargement à un autre. *
@@ -776,13 +805,35 @@ static void change_current_view_support(unsigned int wanted)
cursor = g_loaded_panel_get_cursor(panel);
+ change_editor_items_current_view(new);
+
if (cursor != NULL)
{
g_loaded_panel_set_cursor(new, cursor);
- g_object_unref(G_OBJECT(cursor));
- }
- change_editor_items_current_view(new);
+ /**
+ * A ce stade, le nouveau composant d'affichage n'a pas encore connu son
+ * premier gtk_widget_size_allocate(). Cela viendra avec un événement ultérieur
+ * à celui déclenché pour ce menu.
+ *
+ * Dans les faits, cette situation est notable pour la vue en graphique :
+ * tous les blocs basiques chargés et intégrés dedans ont une position
+ * égale à -1 et une dimension d'un pixel.
+ *
+ * La recherche du bloc présent à une position donnée échoue donc dans la
+ * fonction gtk_graph_display_move_caret_to(), appelée in fine par
+ * g_loaded_panel_scroll_to_cursor().
+ *
+ * Et au final, le curseur d'origine n'est pas transmis, et donc pas
+ * transmissible non plus par la suite.
+ *
+ * On se doit ainsi d'attendre l'attribution des emplacements avant de déplacer
+ * le curseur et de terminer de cet fait les opérations.
+ */
+
+ g_signal_connect(new, "size-allocate", G_CALLBACK(handle_loaded_panel_first_allocation), cursor);
+
+ }
g_object_unref(G_OBJECT(new));