summaryrefslogtreecommitdiff
path: root/src/gui/panels/panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/panels/panel.c')
-rw-r--r--src/gui/panels/panel.c206
1 files changed, 161 insertions, 45 deletions
diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c
index cf4423d..3ad60b6 100644
--- a/src/gui/panels/panel.c
+++ b/src/gui/panels/panel.c
@@ -32,6 +32,7 @@
#include "log.h"
#include "panel-int.h"
+#include "strings.h"
#include "symbols.h"
#include "welcome.h"
#include "../../gtkext/easygtk.h"
@@ -71,8 +72,14 @@ static void switch_panel_node_into_paned(panel_node *, bool, bool);
/* Met en place un nouveau noeud dans une division. */
static void attach_panel_node_to_paned(panel_node *, panel_node *, bool);
-/* Indique si un noeud correspond à la branche recherchée. */
-static bool is_panel_node_matching(const panel_node *, char);
+/* Valorise la correspondance entre un noeud et un chemin. */
+static int compute_panel_node_matching_score(const panel_node *, const char *);
+
+/* Calcule la longueur du plus court chemin vers un 'M'. */
+static size_t _compute_panel_node_main_level(const panel_node *);
+
+/* Recherche le noeud constituant la branche principale. */
+static panel_node *find_main_panel_node_branch(panel_node *, panel_node *);
/* Place au bon endroit un panneau donné. */
static void insert_item_as_panel_node(GPanelItem *, panel_node *, const char *, size_t);
@@ -350,6 +357,9 @@ void load_main_panels(GObject *ref)
item = create_symbols_panel(ref);
g_panel_item_dock(item);
+ item = create_strings_panel(ref);
+ g_panel_item_dock(item);
+
}
@@ -380,7 +390,7 @@ static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const cha
result = (panel_node *)calloc(1, sizeof(panel_node));
- result->path = path[depth];
+ result->path = strdup(path);
result->depth = depth;
result->simple = true;
@@ -438,7 +448,7 @@ static void switch_panel_node_into_paned(panel_node *current, bool horiz, bool f
/* Achève la transformation */
- current->path = '\0';
+ current->path = NULL;
current->simple = false;
@@ -507,7 +517,51 @@ static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, boo
* Paramètres : node = noeud d'où lancer les recherches. *
* target = identifiant de la position visée. *
* *
-* Description : Indique si un noeud correspond à la branche recherchée. *
+* Description : Valorise la correspondance entre un noeud et un chemin. *
+* *
+* Retour : Bilan de l'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compute_panel_node_matching_score(const panel_node *node, const char *target)
+{
+ int result; /* Bilan à retourner */
+ size_t len; /* Longueur de comparaison */
+ size_t i; /* Boucle de parcours */
+
+ if (node->simple)
+ {
+ result = 0;
+
+ len = strlen(node->path);
+ len = MIN(len, strlen(target));
+
+ for (i = 0; i < len; i++)
+ {
+ if (node->path[i] != target[i]) break;
+ else result++;
+ }
+
+ }
+
+ else
+ {
+ result = compute_panel_node_matching_score(node->first, target);
+ result = MAX(result, compute_panel_node_matching_score(node->second, target));
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud d'où lancer les recherches. *
+* *
+* Description : Calcule la longueur du plus court chemin vers un 'M'. *
* *
* Retour : Bilan de l'évaluation. *
* *
@@ -515,16 +569,59 @@ static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, boo
* *
******************************************************************************/
-static bool is_panel_node_matching(const panel_node *node, char target)
+static size_t _compute_panel_node_main_level(const panel_node *node)
{
- if (node->path == target)
- return true;
+ size_t result; /* Plus petit chemin à renvoyer*/
if (node->simple)
- return false;
+ {
+ result = strcspn(&node->path[node->depth], "M");
+
+ if (node->path[node->depth + result] == '\0')
+ result = SIZE_MAX;
- return is_panel_node_matching(node->first, target)
- || is_panel_node_matching(node->second, target);
+ }
+
+ else
+ {
+ result = _compute_panel_node_main_level(node->first);
+ result = MIN(result, _compute_panel_node_main_level(node->second));
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = première branche à analyser. *
+* b = seconde branche à analyser. *
+* *
+* Description : Recherche le noeud constituant la branche principale. *
+* *
+* Retour : Branche principale ou NULL si aucune n'est idéale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static panel_node *find_main_panel_node_branch(panel_node *a, panel_node *b)
+{
+ panel_node *result; /* Trouvaille à remonter */
+ size_t main_a; /* Proximité du 'M' côté a */
+ size_t main_b; /* Proximité du 'M' côté b */
+
+ main_a = _compute_panel_node_main_level(a);
+ main_b = _compute_panel_node_main_level(b);
+
+ if (main_a == SIZE_MAX && main_b == SIZE_MAX)
+ result = NULL;
+
+ else
+ result = (main_a < main_b ? a : b);
+
+ return result;
}
@@ -550,15 +647,17 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const
bool horiz; /* Traduction en composant */
bool first; /* Point d'insertion */
panel_node *new; /* Nouveau noeud créé */
+ int score1; /* Score de la 1ère branche */
+ int score2; /* Score de la 2nde branche */
panel_node *support; /* Noeud d'accueil désigné */
if (node->simple)
{
/* Si on est sur la bonne voie... */
- if (path[depth] == '\0' || path[depth] == node->path)
+ if (compute_panel_node_matching_score(node, path) > 0)
{
/* Le parcours s'arrête ici ! */
- if (path[depth] == '\0' || path[depth + 1] == '\0')
+ if (strcmp(node->path, path) == 0)
gtk_dock_panel_add_widget(GTK_DOCK_STATION(node->station),
G_EDITOR_ITEM(item)->widget,
G_EDITOR_ITEM(item)->name);
@@ -566,13 +665,13 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const
/* On ne peut aller plus loin, on doit diviser... */
else
{
- div = toupper(path[depth + 1]);
+ div = toupper(path[depth]);
first = (div == 'E' || div == 'S');
horiz = (div == 'W' || div == 'E');
switch_panel_node_into_paned(node, horiz, first);
- new = create_simple_panel_node_for_item(item, path, depth + 1);
+ new = create_simple_panel_node_for_item(item, path, depth);
attach_panel_node_to_paned(node, new, !first);
@@ -603,50 +702,64 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const
/* On regarde des autres côtés... */
- else if (is_panel_node_matching(node->first, path[depth]))
- insert_item_as_panel_node(item, node->first, path, depth + (node->first->simple ? 1 : 0));
-
- else if (is_panel_node_matching(node->second, path[depth]))
- insert_item_as_panel_node(item, node->second, path, depth + (node->second->simple ? 1 : 0));
-
- /* On doit diviser qqch... */
else
{
- /* Si l'élément doit passer en force */
- if (isupper(path[depth]))
- {
- div = path[depth];
- first = (div == 'E' || div == 'S');
- horiz = (div == 'W' || div == 'E');
+ score1 = compute_panel_node_matching_score(node->first, path);
+ score2 = compute_panel_node_matching_score(node->second, path);
- switch_panel_node_into_paned(node, horiz, first);
-
- new = create_simple_panel_node_for_item(item, path, depth);
+ /* Si une descente est possible... */
+ if (score1 > 0 || score2 > 0)
+ {
+ if (node->first->simple || node->second->simple)
+ depth++;
- attach_panel_node_to_paned(node, new, !first);
+ if (score1 > score2)
+ insert_item_as_panel_node(item, node->first, path, depth);
- rebuild_panels_interface(node);
+ else
+ insert_item_as_panel_node(item, node->second, path, depth);
}
+ /* Sinon, on doit diviser qqch... */
else
{
- if (is_panel_node_matching(node->second, 'M'))
- support = node->second;
+ /* Si l'élément doit passer en force */
+ if (isupper(path[depth]))
+ {
+ div = path[depth];
+ first = (div == 'E' || div == 'S');
+ horiz = (div == 'W' || div == 'E');
+
+ switch_panel_node_into_paned(node, horiz, first);
+
+ new = create_simple_panel_node_for_item(item, path, depth);
+
+ attach_panel_node_to_paned(node, new, !first);
+
+ rebuild_panels_interface(node);
+
+ }
+
else
- support = node->first;
+ {
+ support = find_main_panel_node_branch(node->first, node->second);
+ if (support == NULL)
+ support = node->first;
- div = toupper(path[depth]);
- first = (div == 'E' || div == 'S');
- horiz = (div == 'W' || div == 'E');
+ div = toupper(path[depth]);
+ first = (div == 'E' || div == 'S');
+ horiz = (div == 'W' || div == 'E');
- switch_panel_node_into_paned(support, horiz, first);
+ switch_panel_node_into_paned(support, horiz, first);
- new = create_simple_panel_node_for_item(item, path, depth);
+ new = create_simple_panel_node_for_item(item, path, depth);
- attach_panel_node_to_paned(support, new, !first);
+ attach_panel_node_to_paned(support, new, !first);
- rebuild_panels_interface(support);
+ rebuild_panels_interface(support);
+
+ }
}
@@ -796,6 +909,7 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi
GtkRequisition first_req; /* Taille demandée par n°1 */
GtkRequisition second_req; /* Taille demandée par n°2 */
gint handle_size; /* Taille de la séparation */
+ panel_node *main_node; /* Branche principale */
gint position; /* Position de la séparation */
bool can_lower; /* Diminution possible ? */
bool can_upper; /* Augmentation possible ? */
@@ -813,8 +927,10 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi
* Définitions des bornes dans chacun des cas.
*/
+ main_node = find_main_panel_node_branch(node->first, node->second);
+
/* Le premier noeud est le principal... */
- if (is_panel_node_matching(node->first, 'M'))
+ if (node->first == main_node)
{
if (GTK_IS_HPANED(node->paned))
position = (space->width * MAIN_PART_PERCENT) / 100;
@@ -827,7 +943,7 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi
}
/* Le second noeud est le principal... */
- else if (is_panel_node_matching(node->second, 'M'))
+ else if (node->second == main_node)
{
if (GTK_IS_HPANED(node->paned))
position = space->width - (space->width * MAIN_PART_PERCENT) / 100;