[gnome-panel] panel: Move to a model where panel objects are all packed



commit 6db6be277ce4fdd3d8f2a1d1c50a6bf06e25d10e
Author: Vincent Untz <vuntz gnome org>
Date:   Wed Mar 30 21:43:52 2011 +0530

    panel: Move to a model where panel objects are all packed
    
    Instead of positioning objects on specific positions on panels, we pack
    them all either at the start or the end. This simplify things a lot, and
    help keep clean panels.
    
    Note that adding/moving objects is broken right now.

 .../org.gnome.gnome-panel.object.gschema.xml.in.in |   10 +-
 data/panel-default-layout.layout                   |   10 +-
 gnome-panel/applet.c                               |   57 +---
 gnome-panel/applet.h                               |    1 -
 gnome-panel/panel-layout.c                         |   18 +-
 gnome-panel/panel-layout.h                         |    6 +-
 gnome-panel/panel-object-loader.c                  |   12 +-
 gnome-panel/panel-schemas.h                        |    2 +-
 gnome-panel/panel-widget.c                         |  364 ++++++++++----------
 gnome-panel/panel-widget.h                         |   24 +-
 gnome-panel/panel.c                                |   20 -
 gnome-panel/panel.h                                |    3 -
 12 files changed, 248 insertions(+), 279 deletions(-)
---
diff --git a/data/org.gnome.gnome-panel.object.gschema.xml.in.in b/data/org.gnome.gnome-panel.object.gschema.xml.in.in
index 4704d34..132147a 100644
--- a/data/org.gnome.gnome-panel.object.gschema.xml.in.in
+++ b/data/org.gnome.gnome-panel.object.gschema.xml.in.in
@@ -10,15 +10,15 @@
       <_summary>Toplevel panel containing object</_summary>
       <_description>The identifier of the toplevel panel which contains this object.</_description>
     </key>
-    <key name="position" type="i">
-      <default>0</default>
-      <_summary>Object's position on the panel</_summary>
-      <_description>The position of this panel object. The position is specified by the number of pixels from the left (or top if vertical) panel edge.</_description>
-    </key>
     <key name="pack-type" enum="org.gnome.gnome-panel.PanelObjectPackType">
       <default>'start'</default>
       <_summary>Interpret position relative to bottom/right edge</_summary>
       <_description>If set to 'end', the position of the object is interpreted relative to the right (or bottom if vertical) edge of the panel.</_description>
     </key>
+    <key name="pack-index" type="i">
+      <default>0</default>
+      <_summary>Object's position on the panel</_summary>
+      <_description>The position of this panel object. The position is specified by the number of pixels from the left (or top if vertical) panel edge.</_description>
+    </key>
   </schema>
 </schemalist>
diff --git a/data/panel-default-layout.layout b/data/panel-default-layout.layout
index 60cf3fe..01c80ae 100644
--- a/data/panel-default-layout.layout
+++ b/data/panel-default-layout.layout
@@ -12,27 +12,27 @@ y-bottom=0
 [Object menu-bar]
 object-iid=PanelInternalFactory::MenuBar
 toplevel-id=top-panel
-position=0
+pack-index=0
 
 [Object clock]
 object-iid=ClockAppletFactory::ClockApplet
 toplevel-id=top-panel
-position=0
 pack-type=end
+pack-index=0
 
 [Object notification-area]
 object-iid=NotificationAreaAppletFactory::NotificationArea
 toplevel-id=top-panel
-position=1
 pack-type=end
+pack-index=1
 
 [Object window-list]
 object-iid=WnckletFactory::WindowListApplet
 toplevel-id=bottom-panel
-position=0
+pack-index=0
 
 [Object workspace-switcher]
 object-iid=WnckletFactory::WorkspaceSwitcherApplet
 toplevel-id=bottom-panel
-position=0
 pack-type=end
+pack-index=0
diff --git a/gnome-panel/applet.c b/gnome-panel/applet.c
index 5a08e34..51ba59e 100644
--- a/gnome-panel/applet.c
+++ b/gnome-panel/applet.c
@@ -832,10 +832,10 @@ panel_applet_save_position (AppletInfo *applet_info,
 {
 	PanelWidget *panel_widget;
 	const char  *toplevel_id;
-	gboolean     right_stick;
-	int          position;
+	AppletData  *applet_data;
 
 	g_return_if_fail (applet_info != NULL);
+	g_return_if_fail (G_IS_OBJECT (applet_info->widget));
 
 	if (!immediate) {
 		if (!queued_position_source)
@@ -856,21 +856,18 @@ panel_applet_save_position (AppletInfo *applet_info,
 
 	panel_widget = panel_applet_get_panel_widget (applet_info);
 
-	right_stick = panel_is_applet_right_stick (applet_info->widget) ? 1 : 0;
-
-	position = panel_applet_get_position (applet_info);
-	if (right_stick && !panel_widget->packed)
-		position = panel_widget->size - position;
+	applet_data = g_object_get_data (G_OBJECT (applet_info->widget),
+					 PANEL_APPLET_DATA);
 
 	g_settings_set_string (applet_info->settings,
 			       PANEL_OBJECT_TOPLEVEL_ID_KEY,
 			       toplevel_id);
 	g_settings_set_enum (applet_info->settings,
 			     PANEL_OBJECT_PACK_TYPE_KEY,
-			     right_stick ? PANEL_OBJECT_PACK_END : PANEL_OBJECT_PACK_START);
+			     applet_data->pack_type);
 	g_settings_set_int (applet_info->settings,
-			    PANEL_OBJECT_POSITION_KEY,
-			    position);
+			    PANEL_OBJECT_PACK_INDEX_KEY,
+			    applet_data->pack_index);
 }
 
 const char *
@@ -951,8 +948,8 @@ panel_applet_register (GtkWidget       *applet,
 		       GDestroyNotify   data_destroy)
 {
 	AppletInfo          *info;
-	int                  pos;
 	PanelObjectPackType  pack_type;
+	int                  pack_index;
 	
 	g_return_val_if_fail (applet != NULL && panel != NULL, NULL);
 
@@ -978,28 +975,11 @@ panel_applet_register (GtkWidget       *applet,
 	registered_applets = g_slist_append (registered_applets, info);
 
 	/* Find where to insert the applet */
-        pos = g_settings_get_int (info->settings, PANEL_OBJECT_POSITION_KEY);
         pack_type = g_settings_get_enum (info->settings, PANEL_OBJECT_PACK_TYPE_KEY);
+        pack_index = g_settings_get_int (info->settings, PANEL_OBJECT_PACK_INDEX_KEY);
 
 	/* Insert it */
-	if (panel_widget_add (panel, applet, pos, pack_type, TRUE) == -1 &&
-	    panel_widget_add (panel, applet, 0, PANEL_OBJECT_PACK_START, FALSE) == -1) {
-		GSList *l;
-
-		for (l = panels; l; l = l->next) {
-			panel = PANEL_WIDGET (l->data);
-
-			if (panel_widget_add (panel, applet,
-					      0, PANEL_OBJECT_PACK_START, FALSE) != -1)
-				break;
-		}
-
-		if (!l) {
-			g_warning (_("Cannot find an empty spot"));
-			panel_layout_delete_object (info->id);
-			return NULL;
-		}
-	}
+	panel_widget_add (panel, applet, pack_type, pack_index, TRUE);
 
 	if (BUTTON_IS_WIDGET (applet) ||
 	    gtk_widget_get_has_window (applet)) {
@@ -1032,19 +1012,6 @@ panel_applet_register (GtkWidget       *applet,
 	return info;
 }
 
-int
-panel_applet_get_position (AppletInfo *applet)
-{
-	AppletData *applet_data;
-
-	g_return_val_if_fail (applet != NULL, 0);
-	g_return_val_if_fail (G_IS_OBJECT (applet->widget), 0);
-
-	applet_data = g_object_get_data (G_OBJECT (applet->widget), PANEL_APPLET_DATA);
-
-	return applet_data->pos;
-}
-
 GSettings *
 panel_applet_get_settings (AppletInfo *applet)
 {
@@ -1064,7 +1031,7 @@ panel_applet_can_freely_move (AppletInfo *applet)
 	return (g_settings_is_writable (applet->settings,
 					PANEL_OBJECT_TOPLEVEL_ID_KEY) &&
 	        g_settings_is_writable (applet->settings,
-					PANEL_OBJECT_POSITION_KEY) &&
+					PANEL_OBJECT_PACK_TYPE_KEY) &&
 	        g_settings_is_writable (applet->settings,
-					PANEL_OBJECT_PACK_TYPE_KEY));
+					PANEL_OBJECT_PACK_INDEX_KEY));
 }
diff --git a/gnome-panel/applet.h b/gnome-panel/applet.h
index 3a6a59b..2de0362 100644
--- a/gnome-panel/applet.h
+++ b/gnome-panel/applet.h
@@ -76,7 +76,6 @@ void        panel_applet_save_position           (AppletInfo *applet_info,
 						  const char *id,
 						  gboolean    immediate);
 
-int         panel_applet_get_position    (AppletInfo *applet);
 GSettings  *panel_applet_get_settings    (AppletInfo *applet);
 
 /* True if all the keys relevant to moving are writable
diff --git a/gnome-panel/panel-layout.c b/gnome-panel/panel-layout.c
index 8aec416..e101c35 100644
--- a/gnome-panel/panel-layout.c
+++ b/gnome-panel/panel-layout.c
@@ -111,8 +111,8 @@ static PanelLayoutKeyDefinition panel_layout_toplevel_keys[] = {
 static PanelLayoutKeyDefinition panel_layout_object_keys[] = {
         { PANEL_OBJECT_IID_KEY,         G_TYPE_STRING   },
         { PANEL_OBJECT_TOPLEVEL_ID_KEY, G_TYPE_STRING   },
-        { PANEL_OBJECT_POSITION_KEY,    G_TYPE_INT      },
-        { PANEL_OBJECT_PACK_TYPE_KEY,   G_TYPE_STRING   }
+        { PANEL_OBJECT_PACK_TYPE_KEY,   G_TYPE_STRING   },
+        { PANEL_OBJECT_PACK_INDEX_KEY,  G_TYPE_INT      }
 };
 
 static gboolean
@@ -600,13 +600,13 @@ void
 panel_layout_object_create (PanelObjectType      type,
                             const char          *type_detail,
                             const char          *toplevel_id,
-                            int                  position,
-                            PanelObjectPackType  pack_type)
+                            PanelObjectPackType  pack_type,
+                            int                  pack_index)
 {
         char *id;
 
         id = panel_layout_object_create_start (type, type_detail,
-                                               toplevel_id, position, pack_type,
+                                               toplevel_id, pack_type, pack_index,
                                                NULL);
 
         if (!id)
@@ -660,8 +660,8 @@ char *
 panel_layout_object_create_start (PanelObjectType       type,
                                   const char           *type_detail,
                                   const char           *toplevel_id,
-                                  int                   position,
                                   PanelObjectPackType   pack_type,
+                                  int                   pack_index,
                                   GSettings           **settings)
 {
         char      *unique_id;
@@ -691,12 +691,12 @@ panel_layout_object_create_start (PanelObjectType       type,
         g_settings_set_string (settings_object,
                                PANEL_OBJECT_TOPLEVEL_ID_KEY,
                                toplevel_id);
-        g_settings_set_int (settings_object,
-                            PANEL_OBJECT_POSITION_KEY,
-                            position);
         g_settings_set_enum (settings_object,
                              PANEL_OBJECT_PACK_TYPE_KEY,
                              pack_type);
+        g_settings_set_int (settings_object,
+                            PANEL_OBJECT_PACK_INDEX_KEY,
+                            pack_index);
 
         g_free (iid);
 
diff --git a/gnome-panel/panel-layout.h b/gnome-panel/panel-layout.h
index 205fc3d..70ba81e 100644
--- a/gnome-panel/panel-layout.h
+++ b/gnome-panel/panel-layout.h
@@ -43,8 +43,8 @@ void  panel_layout_toplevel_create      (GdkScreen            *screen);
 void  panel_layout_object_create        (PanelObjectType       type,
                                          const char           *type_detail,
                                          const char           *toplevel_id,
-                                         int                   position,
-                                         PanelObjectPackType   pack_type);
+                                         PanelObjectPackType   pack_type,
+                                         int                   pack_index);
 
 char      *panel_layout_object_get_gconf_path (const char *object_id);
 GSettings *panel_layout_get_instance_settings (GSettings  *settings_object,
@@ -53,8 +53,8 @@ GSettings *panel_layout_get_instance_settings (GSettings  *settings_object,
 char *panel_layout_object_create_start  (PanelObjectType       type,
                                          const char           *type_detail,
                                          const char           *toplevel_id,
-                                         int                   position,
                                          PanelObjectPackType   pack_type,
+                                         int                   pack_index,
                                          GSettings           **settings);
 void  panel_layout_object_create_finish (const char           *object_id);
 
diff --git a/gnome-panel/panel-object-loader.c b/gnome-panel/panel-object-loader.c
index 504edb1..ffd5048 100644
--- a/gnome-panel/panel-object-loader.c
+++ b/gnome-panel/panel-object-loader.c
@@ -52,8 +52,8 @@ typedef struct {
         char                *settings_path;
         GSettings           *settings;
         char                *toplevel_id;
-        int                  position;
         PanelObjectPackType  pack_type;
+        int                  pack_index;
 } PanelObjectToLoad;
 
 /* Each time those lists get both empty,
@@ -266,10 +266,10 @@ panel_object_loader_queue (const char *id,
         object->settings_path = g_strdup (settings_path);
         object->settings      = g_object_ref (settings);
         object->toplevel_id   = toplevel_id;
-        object->position      = g_settings_get_int (settings,
-                                                    PANEL_OBJECT_POSITION_KEY);
         object->pack_type     = g_settings_get_enum (settings,
                                                      PANEL_OBJECT_PACK_TYPE_KEY);
+        object->pack_index    = g_settings_get_int (settings,
+                                                    PANEL_OBJECT_PACK_INDEX_KEY);
 
         panel_objects_to_load = g_slist_prepend (panel_objects_to_load, object);
 
@@ -287,7 +287,11 @@ panel_object_compare (const PanelObjectToLoad *a,
         else if (a->pack_type != b->pack_type)
                 return a->pack_type - b->pack_type; /* start < center < end */
         else
-                return a->position - b->position;
+                /* note: for packed-end, we explicitly want to start loading
+                 * from the right/bottom instead of left/top to avoid moving
+                 * applets that are on the inside; so the maths are good even
+                 * in this case */
+                return a->pack_index - b->pack_index;
 }
 
 void
diff --git a/gnome-panel/panel-schemas.h b/gnome-panel/panel-schemas.h
index e3b8e77..728e8b2 100644
--- a/gnome-panel/panel-schemas.h
+++ b/gnome-panel/panel-schemas.h
@@ -63,8 +63,8 @@
 #define PANEL_OBJECT_SCHEMA             "org.gnome.gnome-panel.object"
 #define PANEL_OBJECT_IID_KEY            "object-iid"
 #define PANEL_OBJECT_TOPLEVEL_ID_KEY    "toplevel-id"
-#define PANEL_OBJECT_POSITION_KEY       "position"
 #define PANEL_OBJECT_PACK_TYPE_KEY      "pack-type"
+#define PANEL_OBJECT_PACK_INDEX_KEY     "pack-index"
 
 #define PANEL_LAUNCHER_SCHEMA      "org.gnome.gnome-panel.launcher"
 #define PANEL_LOCATION_KEY         "location"
diff --git a/gnome-panel/panel-widget.c b/gnome-panel/panel-widget.c
index 3f33e80..48ae1c6 100644
--- a/gnome-panel/panel-widget.c
+++ b/gnome-panel/panel-widget.c
@@ -108,7 +108,12 @@ static gboolean panel_widget_push_applet_left  (PanelWidget *panel,
 static int
 applet_data_compare (AppletData *ad1, AppletData *ad2)
 {
-	return ad1->pos - ad2->pos;
+	if (ad1->pack_type != ad2->pack_type)
+		return ad1->pack_type - ad2->pack_type; /* start < center < end */
+	else if (ad1->pack_type != PANEL_OBJECT_PACK_END)
+		return ad1->pack_index - ad2->pack_index;
+	else
+		return ad2->pack_index - ad1->pack_index;
 }
 
 static void
@@ -475,7 +480,7 @@ panel_widget_cadd (GtkContainer *container,
 	g_return_if_fail (GTK_IS_WIDGET (widget));
 
 	panel_widget_add (PANEL_WIDGET (container), widget,
-			  0, PANEL_OBJECT_PACK_START, FALSE);
+			  PANEL_OBJECT_PACK_START, 0, FALSE);
 }
 
 static void
@@ -510,58 +515,43 @@ panel_widget_cremove (GtkContainer *container, GtkWidget *widget)
 }
 
 
-/*get the list item of the data on the position pos*/
+/* data should be freed with g_list_free() */
 static GList *
-get_applet_list_pos (PanelWidget *panel,
-		     int          pos)
+get_applet_list_pack (PanelWidget         *panel,
+		      PanelObjectPackType  pack_type)
 {
+	GList *ret;
 	GList *l;
+	GList *prev;
 
 	g_return_val_if_fail (PANEL_IS_WIDGET (panel), NULL);
-	
+
 	for (l = panel->applet_list; l; l = l->next) {
 		AppletData *ad = l->data;
 
-		if (ad->pos <= pos) {
-		       if (ad->pos + ad->cells > pos)
-			       return l;
-		} else
-			return NULL;
+		if (ad->pack_type == pack_type)
+			break;
 	}
 
-	return NULL;
-}
-
-/*tells us if an applet is "stuck" on the right side*/
-int
-panel_widget_is_applet_stuck (PanelWidget *panel_widget,
-			      GtkWidget   *widget)
-{
-	AppletData *applet;
-
-	g_return_val_if_fail (PANEL_IS_WIDGET (panel_widget), FALSE);
-	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+	if (!l)
+		return NULL;
 
-	applet = g_object_get_data (G_OBJECT (widget), PANEL_APPLET_DATA);
-	if (applet) {
-		GList *applet_list, *l;
-		int    end_pos = -1;
-	
-		applet_list = g_list_find (panel_widget->applet_list, applet);
-
-		for (l = applet_list; l; l = l->next) {
-			applet = l->data;
+	ret = g_list_copy (l);
+	for (l = ret; l; l = l->next) {
+		AppletData *ad = l->data;
+		if (ad->pack_type != pack_type)
+			break;
+	}
 
-			if (end_pos != -1 && applet->pos != end_pos)
-				break;
+	if (!l)
+		return ret;
 
-			end_pos = applet->pos + applet->cells;
-			if (end_pos >= panel_widget->size)
-				return TRUE;
-		}
-	}
+	prev = l->prev;
+	if (prev)
+		prev->next = NULL;
+	g_list_free (l);
 
-	return FALSE;
+	return ret;
 }
 
 static int
@@ -829,7 +819,6 @@ panel_widget_push_move (PanelWidget *panel,
 			AppletData  *ad,
 			int          moveby)
 {
-	AppletData *pad;
 	int finalpos;
 	GList *list;
 
@@ -845,6 +834,8 @@ panel_widget_push_move (PanelWidget *panel,
 	finalpos = ad->constrained + moveby;
 
 	if (ad->constrained < finalpos) {
+		AppletData *pad;
+
 		while (ad->constrained < finalpos)
 			if (!panel_widget_push_applet_right (panel, list, 1))
 				break;
@@ -855,51 +846,94 @@ panel_widget_push_move (PanelWidget *panel,
 				gtk_widget_queue_resize (GTK_WIDGET (panel));
 		}
 	} else {
+		AppletData *nad;
+
                 while (ad->constrained > finalpos)
 			if (!panel_widget_push_applet_left (panel, list, 1))
 				break;
+
+		if (list->next) {
+			nad = list->next->data;
+			if (nad->expand_major)
+				gtk_widget_queue_resize (GTK_WIDGET (panel));
+		}
 	}
 }
 
 
-/*this is a special function and may fail if called improperly, it works
-only under special circumstance when we know there is nothing from
-old_size to panel->size*/
+/* Note: this can only be called at the beginning of size_allocate, which means
+ * that ad->constrained doesn't matter yet (it will be set to the correct
+ * value in size_allocate). */
 static void
-panel_widget_right_stick(PanelWidget *panel,int old_size)
+panel_widget_update_packed_start (PanelWidget *panel)
 {
-	int i,pos;
-	GList *list,*prev;
+	GList *list,*l;
 	AppletData *ad;
+	int size_all = 0;
+	int pos_next;
 
-	g_return_if_fail(PANEL_IS_WIDGET(panel));
-	g_return_if_fail(old_size>=0);
-	
-	if(old_size>=panel->size ||
-	   panel->packed)
-	   	return;
-	
-	list = get_applet_list_pos(panel,old_size-1);
+	if (panel->packed)
+		return;
+
+	list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_START);
+
+	/* get size used by the objects */
+	for (l = list; l; l = l->next) {
+		ad = l->data;
+		size_all += ad->cells;
+	}
+
+	/* update absolute position of all applets based on this information,
+	 * starting with the first object */
+	pos_next = 0;
+	l = list;
+
+	while (l) {
+		ad = l->data;
+		ad->abs_pos = pos_next;
+		pos_next += 1; /* += ad->cells is the exact right value, but 1
+				  is enough for the order */
+		l = l->next;
+	}
+
+	g_list_free (list);
+}
+
+/* Note: only use this function when you can; see comment above
+ * panel_widget_update_packed_start() */
+static void
+panel_widget_update_packed_end (PanelWidget *panel)
+{
+	GList *list,*l;
+	AppletData *ad;
+	int size_all = 0;
+	int pos_next;
 
-	if(!list)
+	if (panel->packed)
 		return;
-	
-	pos = panel->size-1;
 
-	ad = list->data;
-	do { 
-		i = ad->pos;
-		ad->pos = ad->constrained = pos--;
-		ad->cells = 1;
-		prev = list;
-		list = g_list_previous(list);
-		if(!list)
-			break;
-		ad = list->data;
-	} while(ad->pos + ad->cells == i);
+	list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_END);
+
+	/* get size used by the objects */
+	for (l = list; l; l = l->next) {
+		ad = l->data;
+		size_all += ad->cells;
+	}
 
-	for (list = prev; list; list = list->next)
-		emit_applet_moved (panel, list->data);
+	/* update absolute position of all applets based on this information,
+	 * starting with the first object */
+	pos_next = panel->size - size_all;
+	l = list;
+
+	while (l) {
+		ad = l->data;
+		ad->abs_pos = pos_next;
+		pos_next += 1; /* += ad->cells is the exact right value, but 1
+				  is enough for the order */
+		l = l->next;
+	}
+
+	g_list_free (list);
 }
 
 static void
@@ -1069,7 +1103,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 	PanelWidget *panel;
 	GList *list;
 	int i;
-	int old_size;
 	gboolean ltr;
 
 	g_return_if_fail(PANEL_IS_WIDGET(widget));
@@ -1077,7 +1110,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 
 	panel = PANEL_WIDGET(widget);
 
-	old_size = panel->size;
 	ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR;
 	
 	gtk_widget_set_allocation (widget, allocation);
@@ -1092,8 +1124,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 		panel->size = allocation->width;
 	else
 		panel->size = allocation->height;
-	if(old_size<panel->size)
-		panel_widget_right_stick(panel,old_size);
 
 	if (panel->packed) {
 		/* we're assuming the order is the same as the one that was
@@ -1150,8 +1180,8 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 
 	} else { /*not packed*/
 
-		/* First make sure there's enough room on the left */
-		i = 0;
+		/* First pass: set ad->cells so that we can know the absolute
+		 * position of objects. */
 		for (list = panel->applet_list;
 		     list != NULL;
 		     list = g_list_next (list)) {
@@ -1171,8 +1201,20 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 				ad->cells = ad->size_hints [ad->size_hints_len - 1];
 				ad->min_cells = ad->size_hints [ad->size_hints_len - 1];
 			}
+		}
 
-			ad->constrained = ad->pos;
+		/* Re-compute the position of objects, based on their size */
+		panel_widget_update_packed_start (panel);
+		panel_widget_update_packed_end (panel);
+
+		/* Second pass: try to position from the start, to make sure
+		 * there's enough room. We don't use size hints yet. */
+		i = 0;
+		for (list = panel->applet_list;
+		     list != NULL;
+		     list = g_list_next (list)) {
+			AppletData *ad = list->data;
+			ad->constrained = ad->abs_pos;
 
 			if (ad->constrained < i)
 				ad->constrained = i;
@@ -1180,7 +1222,8 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 			i = ad->constrained + ad->cells;
 		}
 
-		/* Now expand from the right */
+		/* Third pass: now expand from the end, and start using size
+		 * hints if we need more room */
 		i = panel->size;
 		for(list = g_list_last(panel->applet_list);
 		    list!=NULL;
@@ -1222,6 +1265,7 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 			}
 		}
 
+		/* Last pass: actually allocate the size for each object */
 		for(list = panel->applet_list;
 		    list!=NULL;
 		    list = g_list_next(list)) {
@@ -1250,6 +1294,8 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 			gtk_widget_size_allocate(ad->applet,&challoc);
 		}
 	}
+
+
 	if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
 		panel->thick = allocation->height;
 	else
@@ -2177,108 +2223,89 @@ bind_top_applet_events (GtkWidget *widget)
 				       bind_applet_events, widget);
 }
 
-static int
-panel_widget_find_empty_pos(PanelWidget *panel, int pos)
-{
-	int i;
-	int right=-1,left=-1;
-	GList *list;
-
-	g_return_val_if_fail(PANEL_IS_WIDGET(panel),-1);
-
-	if(pos>=panel->size)
-		pos = panel->size-1;
-
-	if (pos <= 0)
-		pos = 0;
-
-	if(!panel->applet_list)
-		return pos;
-
-	list = panel->applet_list;
-
-	for (i = pos; i < panel->size; i++) {
-		list = walk_up_to (i, list);
-		if ( ! is_in_applet (i, list->data)) {
-			right = i;
-			break;
-		}
-	}
-
-	for(i = pos; i >= 0; i--) {
-		list = walk_up_to (i, list);
-		if ( ! is_in_applet (i, list->data)) {
-			left = i;
-			break;
-		}
-	}
-
-	if (left == -1) {
-		if (right == -1)
-			return -1;
-		else
-			return right;
-	} else {
-		if (right == -1)
-			return left;
-		else
-			return abs (left - pos) > abs (right - pos) ?
-				right : left;
-	}
-}
-
-int
+void
 panel_widget_add (PanelWidget         *panel,
 		  GtkWidget           *applet,
-		  int                  pos,
 		  PanelObjectPackType  pack_type,
-		  gboolean             insert_at_pos)
+		  int                  pack_index,
+		  gboolean             use_pack_index)
 {
 	AppletData *ad = NULL;
 
-	g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
-	g_return_val_if_fail (GTK_IS_WIDGET (applet), -1);
-
-	if (pack_type == PANEL_OBJECT_PACK_END) {
-		if (!panel->packed)
-			pos = panel->size - pos;
-		else
-			pos = -1;
-	}
+	g_return_if_fail (PANEL_IS_WIDGET (panel));
+	g_return_if_fail (GTK_IS_WIDGET (applet));
 
 	ad = g_object_get_data (G_OBJECT (applet), PANEL_APPLET_DATA);
 
-	if (ad != NULL)
-		pos = ad->pos;
+	if (ad != NULL) {
+		pack_type = ad->pack_type;
+		pack_index = ad->pack_index;
+	}
 
-	if (!insert_at_pos || pos < 0) {
+	if (!use_pack_index || pack_index < 0) {
 		if (panel->packed) {
-			if (get_applet_list_pos (panel, pos)) 
-				/*this is a slight hack so that this applet
-				  is inserted AFTER an applet with this pos
-				  number*/
-				pos++;
+			/* add at the end of packed panels */
+			AppletData *ad;
+			GList *list,*l;
+
+			list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_END);
+			if (list) {
+				for (l = list; l; l = l->next) {
+					ad = l->data;
+					ad->pack_index += 1;
+					emit_applet_moved (panel, ad);
+				}
+				pack_type = PANEL_OBJECT_PACK_END;
+				pack_index = 0;
+			} else {
+				list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_START);
+
+				if (!list) {
+					pack_type = PANEL_OBJECT_PACK_START;
+					pack_index = 0;
+				} else {
+					l = g_list_last (list);
+					AppletData *ad = l->data;
+					pack_type = ad->pack_type;
+					pack_index = ad->pack_index + 1;
+				}
+			}
+
+			g_list_free (list);
 		} else {
-			int newpos = panel_widget_find_empty_pos (panel, pos);
-			if (newpos >= 0)
-				pos = newpos;
-			else if (get_applet_list_pos (panel, pos)) 
-				/*this is a slight hack so that this applet
-				  is inserted AFTER an applet with this pos
-				  number*/
-				pos++;
+			GList *list,*l;
+
+			list = get_applet_list_pack (panel, pack_type);
+
+			l = NULL;
+			if (pack_type == PANEL_OBJECT_PACK_START)
+				l = g_list_last (list);
+			else if  (pack_type == PANEL_OBJECT_PACK_END)
+				l = list;
+			else
+				g_assert_not_reached ();
+
+			if (!l)
+				pack_index = 0;
+			else {
+				AppletData *ad = l->data;
+				pack_index = ad->pack_index + 1;
+			}
+
+			g_list_free (list);
 		}
 	}
 
-	if(pos==-1) return -1;
-
 	if (ad == NULL) {
 		ad = g_new (AppletData, 1);
 		ad->applet = applet;
 		ad->cells = 1;
 		ad->min_cells = 1;
-		ad->pos = pos;
-		ad->constrained = pos;
+		ad->pack_type = pack_type;
+		ad->pack_index = pack_index;
+		/* both abs_pos and constrained will get updated later */
+		ad->abs_pos = 0;
+		ad->constrained = 0;
 		ad->drag_off = 0;
 		ad->no_die = 0;
 		ad->size_constrained = FALSE;
@@ -2296,25 +2323,14 @@ panel_widget_add (PanelWidget         *panel,
 		g_list_insert_sorted(panel->applet_list,ad,
 				     (GCompareFunc)applet_data_compare);
 
-	/*this will get done right on size allocate!*/
-	if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
-		gtk_fixed_put(GTK_FIXED(panel),applet,
-			      pos,0);
-	else
-		gtk_fixed_put(GTK_FIXED(panel),applet,
-			      0,pos);
-
+	/* the applet will be positioned on size allocate */
+	gtk_fixed_put (GTK_FIXED (panel), applet, 0, 0);
 
 	gtk_widget_queue_resize(GTK_WIDGET(panel));
 
 	g_signal_emit (G_OBJECT(panel),
 		       panel_widget_signals[APPLET_ADDED_SIGNAL],
 		       0, applet);
-	
-	/*NOTE: forbidden list is not updated on addition, use the
-	function above for the panel*/
-
-	return pos;
 }
 
 gboolean
diff --git a/gnome-panel/panel-widget.h b/gnome-panel/panel-widget.h
index 99aa7d7..b338d4c 100644
--- a/gnome-panel/panel-widget.h
+++ b/gnome-panel/panel-widget.h
@@ -56,7 +56,16 @@ struct _AppletSizeHintsAlloc {
 struct _AppletData
 {
 	GtkWidget *	applet;
-	int		pos;
+
+	PanelObjectPackType pack_type;
+	int		    pack_index;
+
+	/* TODO hacky workaround to keep everything working (move functions */
+	int             pos;
+	/* absolute position from the left, after taking packing into account */
+	int             abs_pos;
+	/* constrained position from the left, after taking other objects into
+	 * account */
 	int             constrained;
 	int		cells;
 	int             min_cells;
@@ -143,13 +152,13 @@ GtkWidget *	panel_widget_new		(PanelToplevel  *toplevel,
 						 gboolean        packed,
 						 GtkOrientation  orient,
 						 int             sz);
-/*add an applet to the panel, preferably at position pos, if insert_at_pos
-  is on, we REALLY want to insert at the pos given by pos*/
-int		panel_widget_add		(PanelWidget         *panel,
+/* add an applet to the panel; if use_pack_index is FALSE, pack_index is ignored
+ * and the applet is appended at the end of the pack list for pack_style */
+void		panel_widget_add		(PanelWidget         *panel,
 						 GtkWidget           *applet,
-						 int                  pos,
 						 PanelObjectPackType  pack_style,
-						 gboolean             insert_at_pos);
+						 int                  pack_index,
+						 gboolean             use_pack_index);
 
 /*move applet to a different panel*/
 int		panel_widget_reparent		(PanelWidget *old_panel,
@@ -184,9 +193,6 @@ void		panel_widget_draw_icon		(PanelWidget *panel,
 						 ButtonWidget *applet);
 
 
-/*tells us if an applet is "stuck" on the right side*/
-int		panel_widget_is_applet_stuck	(PanelWidget *panel,
-						 GtkWidget *applet);
 /*get pos of the cursor location in panel coordinates*/
 int		panel_widget_get_cursorloc	(PanelWidget *panel);
 
diff --git a/gnome-panel/panel.c b/gnome-panel/panel.c
index 6784f00..3c8db8a 100644
--- a/gnome-panel/panel.c
+++ b/gnome-panel/panel.c
@@ -1317,26 +1317,6 @@ panel_screen_from_panel_widget (PanelWidget *panel)
 	return gtk_window_get_screen (GTK_WINDOW (panel->toplevel));
 }
 
-gboolean
-panel_is_applet_right_stick (GtkWidget *applet)
-{
-	GtkWidget   *parent;
-	PanelWidget *panel_widget;
-
-	g_return_val_if_fail (GTK_IS_WIDGET (applet), FALSE);
-
-	parent = gtk_widget_get_parent (applet);
-
-	g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
-
-	panel_widget = PANEL_WIDGET (parent);
-
-	if (!panel_toplevel_get_expand (panel_widget->toplevel))
-		return FALSE;
-
-	return panel_widget_is_applet_stuck (panel_widget, applet);
-}
-
 static void
 panel_delete_without_query (PanelToplevel *toplevel)
 {
diff --git a/gnome-panel/panel.h b/gnome-panel/panel.h
index c657700..3630b8d 100644
--- a/gnome-panel/panel.h
+++ b/gnome-panel/panel.h
@@ -24,9 +24,6 @@ PanelData *panel_setup (PanelToplevel *toplevel);
 
 GdkScreen *panel_screen_from_panel_widget  (PanelWidget *panel);
 
-gboolean panel_is_applet_right_stick (GtkWidget *applet);
-
-
 gboolean panel_check_dnd_target_data (GtkWidget      *widget,
 				      GdkDragContext *context,
 				      guint          *ret_info,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]