← Back to team overview

cairo-dock-team team mailing list archive

lp:~cairo-dock-team/cairo-dock-plug-ins/desklet-rendering-pan-view into lp:cairo-dock-plug-ins

 

Tofe has proposed merging lp:~cairo-dock-team/cairo-dock-plug-ins/desklet-rendering-pan-view into lp:cairo-dock-plug-ins.

Requested reviews:
  Tofe (chris-chapuis)


Added view "Viewport", which is alike "Slide", but with panning possibilites. Also default view of "Folders" is now "Viewport".
-- 
https://code.launchpad.net/~cairo-dock-team/cairo-dock-plug-ins/desklet-rendering-pan-view/+merge/30172
Your team Cairo-Dock Team is subscribed to branch lp:cairo-dock-plug-ins.
=== modified file 'Folders/src/applet-load-icons.c'
--- Folders/src/applet-load-icons.c	2010-07-17 00:33:47 +0000
+++ Folders/src/applet-load-icons.c	2010-07-17 12:02:42 +0000
@@ -353,7 +353,7 @@
 		pList = g_list_prepend (pList, pIcon);
 	}
 	pList = g_list_reverse (pList);
-	CD_APPLET_LOAD_MY_ICONS_LIST (pList, myConfig.cRenderer, "Slide", NULL);
+	CD_APPLET_LOAD_MY_ICONS_LIST (pList, myConfig.cRenderer, "Viewport", NULL);
 	myData.iNbIcons = myConfig.iNbIcons;
 	
 	//\_______________________ On se place en ecoute.

=== modified file 'desklet-rendering/src/CMakeLists.txt'
--- desklet-rendering/src/CMakeLists.txt	2010-07-06 00:03:56 +0000
+++ desklet-rendering/src/CMakeLists.txt	2010-07-17 12:02:42 +0000
@@ -9,6 +9,7 @@
 	rendering-desklet-simple.c 		rendering-desklet-simple.h
 	rendering-desklet-decorations.c rendering-desklet-decorations.h
 	rendering-desklet-slide.c 		rendering-desklet-slide.h
+	rendering-desklet-viewport.c 		rendering-desklet-viewport.h
 	rendering-struct.h
 )
 

=== modified file 'desklet-rendering/src/rendering-desklet-slide.c' (properties changed: +x to -x)
=== modified file 'desklet-rendering/src/rendering-desklet-slide.h' (properties changed: +x to -x)
=== added file 'desklet-rendering/src/rendering-desklet-viewport.c'
--- desklet-rendering/src/rendering-desklet-viewport.c	1970-01-01 00:00:00 +0000
+++ desklet-rendering/src/rendering-desklet-viewport.c	2010-07-17 12:02:42 +0000
@@ -0,0 +1,707 @@
+/**
+* This file is a part of the Cairo-Dock project
+*
+* Copyright : (C) see the 'copyright' file.
+* E-mail    : see the 'copyright' file.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 3
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <math.h>
+#include <cairo-dock.h>
+
+#include "rendering-desklet-viewport.h"
+
+#define _cairo_dock_set_path_as_current(...) _cairo_dock_set_vertex_pointer(pVertexTab)
+
+
+static gboolean on_enter_icon_viewport (gpointer pUserData, Icon *pPointedIcon, CairoContainer *pContainer, gboolean *bStartAnimation)
+{
+	gtk_widget_queue_draw (pContainer->pWidget);  // et oui, on n'a rien d'autre a faire.
+	
+	return CAIRO_DOCK_LET_PASS_NOTIFICATION;
+}
+
+static inline void _viewport_pan_delta(CairoDesklet *pDesklet, double fDeltaX, double fDeltaY)
+{
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	pViewportConf->fCurrentPanXSpeed = fDeltaX;
+	pViewportConf->fCurrentPanYSpeed = fDeltaY;
+	pViewportConf->iCurrentOffsetX += fDeltaX;
+	pViewportConf->iCurrentOffsetY += fDeltaY;
+	if (pViewportConf->iCurrentOffsetX < 0)
+	{
+		pViewportConf->iCurrentOffsetX = 0;
+		pViewportConf->fCurrentPanXSpeed = 0;
+	}
+	else if( pViewportConf->iCurrentOffsetX > pViewportConf->iMaxOffsetX )
+	{
+		pViewportConf->iCurrentOffsetX = pViewportConf->iMaxOffsetX;
+		pViewportConf->fCurrentPanXSpeed = 0;
+	}
+	if (pViewportConf->iCurrentOffsetY < 0)
+	{
+		pViewportConf->iCurrentOffsetY = 0;
+		pViewportConf->fCurrentPanYSpeed = 0;
+	}
+	else if( pViewportConf->iCurrentOffsetY > pViewportConf->iMaxOffsetY )
+	{
+		pViewportConf->iCurrentOffsetY = pViewportConf->iMaxOffsetY;
+		pViewportConf->fCurrentPanYSpeed = 0;
+	}
+
+	gtk_widget_queue_draw (pDesklet->container.pWidget);
+}
+
+static gboolean on_update_desklet (gpointer pUserData, CairoDesklet *pDesklet, gboolean *bContinueAnimation)
+{
+	if (pDesklet->icons != NULL)
+	{
+		CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+		if (pViewportConf == NULL)
+			return CAIRO_DOCK_LET_PASS_NOTIFICATION;
+		
+		if (! pDesklet->container.bInside)  // on est en-dehors du desklet, on ralentit.
+		{
+			_viewport_pan_delta (pDesklet, pViewportConf->fCurrentPanXSpeed*.85, pViewportConf->fCurrentPanYSpeed*.85);
+			if (fabs (pViewportConf->fCurrentPanXSpeed)+fabs (pViewportConf->fCurrentPanYSpeed) < pViewportConf->iIconSize/15)
+			// vitesse de translation epsilonesque, on quitte.
+			{
+				pViewportConf->fCurrentPanXSpeed = 0;
+				pViewportConf->fCurrentPanYSpeed = 0;
+				return CAIRO_DOCK_LET_PASS_NOTIFICATION;
+			}
+			*bContinueAnimation = TRUE;
+		}
+		else
+		{
+			double fDeltaX = 0;
+			double fDeltaY = 0;
+			// si on est dans la marge de 20% de la largeur du desklet a gauche,
+			// alors on translate a droite
+			if (pDesklet->container.iMouseX <= pDesklet->container.iWidth*0.2)
+			{
+				// La force de translation va de 0 (lorsqu'on est a 20%) jusqu'a
+				// pViewportConf->iIconSize / 2. (lorsqu'on est a 0%)
+				fDeltaX = (pViewportConf->iIconSize / 10) *
+									(pDesklet->container.iWidth*0.2 - pDesklet->container.iMouseX)/(pDesklet->container.iWidth*0.2);
+				*bContinueAnimation = TRUE;
+			}
+			// si on est dans la marge de 20% de la largeur du desklet a droite,
+			// alors on translate a gauche (-1)
+			else if( pDesklet->container.iMouseX >= pDesklet->container.iWidth*0.8 )
+			{
+				// La force de translation va de 0 (lorsqu'on est a 80%) jusqu'a
+				// pViewportConf->iIconSize / 2. (lorsqu'on est a 100%)
+				fDeltaX = -(pViewportConf->iIconSize / 10) *
+									 (pDesklet->container.iMouseX - pDesklet->container.iWidth*0.8)/(pDesklet->container.iWidth*0.2);
+				*bContinueAnimation = TRUE;
+			}
+			// si on est dans la marge de 20% de la hauteur du desklet en haut,
+			// alors on translate en bas
+			if (pDesklet->container.iMouseY <= pDesklet->container.iHeight*0.2)
+			{
+				// La force de translation va de 0 (lorsqu'on est a 20%) jusqu'a
+				// pViewportConf->iIconSize / 2. (lorsqu'on est a 0%)
+				fDeltaY = -(pViewportConf->iIconSize / 10) *
+									 (pDesklet->container.iHeight*0.2 - pDesklet->container.iMouseY)/(pDesklet->container.iHeight*0.2);
+				*bContinueAnimation = TRUE;
+			}
+			// si on est dans la marge de 20% de la hauteur du desklet en bas,
+			// alors on translate en haut (-1)
+			else if( pDesklet->container.iMouseY >= pDesklet->container.iHeight*0.8 )
+			{
+				// La force de translation va de 0 (lorsqu'on est a 80%) jusqu'a
+				// pViewportConf->iIconSize / 2. (lorsqu'on est a 100%)
+				fDeltaY = (pViewportConf->iIconSize / 10) *
+									(pDesklet->container.iMouseY - pDesklet->container.iHeight*0.8)/(pDesklet->container.iHeight*0.2);
+				*bContinueAnimation = TRUE;
+			}
+			if( *bContinueAnimation == TRUE )
+			{
+				_viewport_pan_delta( pDesklet, fDeltaX, fDeltaY );
+			}
+			else
+			{
+				pViewportConf->fCurrentPanXSpeed = 0.;
+				pViewportConf->fCurrentPanYSpeed = 0.;
+			}
+		}
+	}
+	return CAIRO_DOCK_LET_PASS_NOTIFICATION;
+}
+
+static gboolean on_mouse_move (gpointer pUserData, CairoDesklet *pDesklet, gboolean *bStartAnimation)
+{
+	if (pDesklet->icons != NULL)
+	{
+		CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+		if (pViewportConf == NULL)
+			return CAIRO_DOCK_LET_PASS_NOTIFICATION;
+		if (pViewportConf->bInfiniteWidth && (pDesklet->container.iMouseX <= pDesklet->container.iWidth*0.2 || pDesklet->container.iMouseX >= pDesklet->container.iWidth*0.8))
+			*bStartAnimation = TRUE;
+		if (pViewportConf->bInfiniteHeight && (pDesklet->container.iMouseY <= pDesklet->container.iHeight*0.2 || pDesklet->container.iMouseY >= pDesklet->container.iHeight*0.8))
+			*bStartAnimation = TRUE;
+	}
+	return CAIRO_DOCK_LET_PASS_NOTIFICATION;
+}
+
+static CDViewportParameters *configure (CairoDesklet *pDesklet, gpointer *pConfig)  // gboolean, int, gdouble[4]
+{
+	CDViewportParameters *pViewportConf = g_new0 (CDViewportParameters, 1);
+	if (pConfig != NULL)
+	{
+		pViewportConf->bRoundedRadius = GPOINTER_TO_INT (pConfig[0]);
+		pViewportConf->iRadius = GPOINTER_TO_INT (pConfig[1]);
+		if (pConfig[2] != NULL)
+			memcpy (pViewportConf->fLineColor, pConfig[2], 4 * sizeof (gdouble));
+	}
+	
+	pViewportConf->iLineWidth = 2;
+	pViewportConf->iGapBetweenIcons = 10;
+	pViewportConf->iMinimumIconSize = 48;
+	pViewportConf->iCurrentOffsetX = 0;
+	pViewportConf->iCurrentOffsetY = 0;
+	pViewportConf->fCurrentPanXSpeed = 0;
+	pViewportConf->fCurrentPanYSpeed = 0;
+	pViewportConf->iMaxOffsetX = 0;
+	pViewportConf->iMaxOffsetY = 0;
+	pViewportConf->bInfiniteHeight=TRUE;
+	pViewportConf->bInfiniteWidth=FALSE;
+	
+	cairo_dock_register_notification_on_container (CAIRO_CONTAINER (pDesklet), CAIRO_DOCK_ENTER_ICON, (CairoDockNotificationFunc) on_enter_icon_viewport, CAIRO_DOCK_RUN_FIRST, NULL);
+	
+	cairo_dock_register_notification_on_container (CAIRO_CONTAINER (pDesklet), CAIRO_DOCK_UPDATE_DESKLET, (CairoDockNotificationFunc) on_update_desklet, CAIRO_DOCK_RUN_AFTER, NULL);
+	cairo_dock_register_notification_on_container (CAIRO_CONTAINER (pDesklet), CAIRO_DOCK_MOUSE_MOVED, (CairoDockNotificationFunc) on_mouse_move, CAIRO_DOCK_RUN_AFTER, NULL);
+	
+	return pViewportConf;
+}
+
+
+static inline void _compute_icons_grid (CairoDesklet *pDesklet, CDViewportParameters *pViewportConf)
+{
+	pViewportConf->fMargin = (pViewportConf->bRoundedRadius ?
+		.5 * pViewportConf->iLineWidth + (1. - sqrt (2) / 2) * pViewportConf->iRadius :
+		.5 * pViewportConf->iLineWidth + .5 * pViewportConf->iRadius);
+	
+	int iNbIcons = 0;
+	Icon *pIcon;
+	GList *ic;
+	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
+	{
+		pIcon = ic->data;
+		if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
+			iNbIcons ++;
+	}
+	pViewportConf->iNbIcons = iNbIcons;
+	
+	double w = pDesklet->container.iWidth - 2 * pViewportConf->fMargin;
+	double h = pDesklet->container.iHeight - 2 * pViewportConf->fMargin;
+	int dh = myLabels.iLabelSize;  // taille verticale ajoutee a chaque icone.
+	int dw = 2 * dh;  // taille horizontale ajoutee a chaque icone.
+	int di = pViewportConf->iGapBetweenIcons;  // ecart entre 2 lignes/colonnes.
+	
+	int p, q;  // nombre de lignes et colonnes.
+	int iSize;
+	pViewportConf->iIconSize = 0, pViewportConf->iNbLines = 0, pViewportConf->iNbColumns = 0;
+	//g_print ("%d icones sur %dx%d (%d)\n", pViewportConf->iNbIcons, (int)w, (int)h, myLabels.iLabelSize);
+	for (p = 1; p <= pViewportConf->iNbIcons; p ++)
+	{
+		q = (int) ceil ((double)pViewportConf->iNbIcons / p);
+		iSize = MIN ((h - (p - 1) * di) / p - dh, (w - (q - 1) * di) / q - dw);
+		//g_print ("  %dx%d -> %d\n", p, q, iSize);
+		if (iSize > pViewportConf->iIconSize)
+		{
+			pViewportConf->iIconSize = iSize;
+			pViewportConf->iNbLines = p;
+			pViewportConf->iNbColumns = q;
+		}
+		else if(iSize > 0) // there is only one maximum
+		{
+			break;
+		}
+	}
+	// si les icones sont trop petites, et qu'on a une largeur et/ou une
+	// hauteur infinie(s), essayer d'avoir au moins une taille minimale
+	if(  pViewportConf->iIconSize < pViewportConf->iMinimumIconSize &&
+	    (pViewportConf->bInfiniteWidth || pViewportConf->bInfiniteHeight) )
+	{
+		if( pViewportConf->bInfiniteWidth && pViewportConf->bInfiniteHeight )
+		{
+			// surface infinie: on garde le meme nb de colonnes&lignes,
+			// mais on met la taille d'icone a iMinimumIconSize
+			pViewportConf->iIconSize = pViewportConf->iMinimumIconSize;
+		}
+		else if( pViewportConf->bInfiniteHeight )
+		{
+			// hauteur infinie et largeur fixe: on calcule le nombre de colonnes
+			// maxi avec pViewportConf->iIconSize = pViewportConf->iMinimumIconSize
+			pViewportConf->iIconSize = pViewportConf->iMinimumIconSize;
+			pViewportConf->iNbColumns = (w + di) / ( pViewportConf->iIconSize + dw + di );
+			if( pViewportConf->iNbColumns < 1 )
+			{
+				pViewportConf->iNbColumns = 1;
+				pViewportConf->iIconSize = w - dw; 
+			}
+			pViewportConf->iNbLines = (int) ceil ((double)pViewportConf->iNbIcons / pViewportConf->iNbColumns);
+		}
+		else if( pViewportConf->bInfiniteWidth )
+		{
+			// largeur infinie et hauteur fixe: on calcule le nombre de lignes
+			// maxi avec pViewportConf->iIconSize = pViewportConf->iMinimumIconSize
+			pViewportConf->iIconSize = pViewportConf->iMinimumIconSize;
+			pViewportConf->iNbLines = (h + di) / ( pViewportConf->iIconSize + dh + di );
+			if( pViewportConf->iNbLines < 1 )
+			{
+				pViewportConf->iNbLines = 1;
+				pViewportConf->iIconSize = h - dh; 
+			}
+			pViewportConf->iNbColumns = (int) ceil ((double)pViewportConf->iNbIcons / pViewportConf->iNbLines);
+		}
+		// on calcule l'offset maximal atteignable en X
+		pViewportConf->iMaxOffsetX = MAX(( pViewportConf->iIconSize + dw + di )*pViewportConf->iNbColumns - (w + di), 0);
+		// on calcule l'offset maximal atteignable en Y
+		pViewportConf->iMaxOffsetY = MAX(( pViewportConf->iIconSize + dh + di )*pViewportConf->iNbLines - (h + di), 0);
+	}
+}
+
+static void load_data (CairoDesklet *pDesklet)
+{
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	if (pViewportConf == NULL)
+		return ;
+	
+	_compute_icons_grid (pDesklet, pViewportConf);
+}
+
+
+static void free_data (CairoDesklet *pDesklet)
+{
+	cairo_dock_remove_notification_func_on_container (CAIRO_CONTAINER (pDesklet), CAIRO_DOCK_ENTER_ICON, (CairoDockNotificationFunc) on_enter_icon_viewport, NULL);
+	
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	if (pViewportConf == NULL)
+		return ;
+	
+	g_free (pViewportConf);
+	pDesklet->pRendererData = NULL;
+}
+
+
+static void set_icon_size (CairoDesklet *pDesklet, Icon *pIcon)
+{
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	if (pViewportConf == NULL)
+		return ;
+	
+	if (pIcon == pDesklet->pIcon)
+	{
+		pIcon->fWidth = 0.;
+		pIcon->fHeight = 0.;
+	}
+	else
+	{
+		pIcon->fWidth = pViewportConf->iIconSize;
+		pIcon->fHeight = pViewportConf->iIconSize;
+	}
+}
+
+static void calculate_icons (CairoDesklet *pDesklet)
+{
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	if (pViewportConf == NULL)
+		return ;
+	
+	_compute_icons_grid (pDesklet, pViewportConf);
+	cd_debug ("pViewportConf->iIconSize : %d\n", pViewportConf->iIconSize);
+	
+	Icon *pIcon = pDesklet->pIcon;
+	if (pIcon != NULL)  // on ne veut pas charger cette icone.
+	{
+		pIcon->fWidth = -1;
+		pIcon->fHeight = -1;
+	}
+	
+	GList* ic;
+	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
+	{
+		pIcon = ic->data;
+		if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
+		{
+			pIcon->fWidth = -1;
+			pIcon->fHeight = -1;
+		}
+		else
+		{
+			pIcon->fWidth = pViewportConf->iIconSize;
+			pIcon->fHeight = pViewportConf->iIconSize;
+		
+			pIcon->fScale = 1.;
+			pIcon->fAlpha = 1.;
+			pIcon->fWidthFactor = 1.;
+			pIcon->fHeightFactor = 1.;
+			pIcon->fGlideScale = 1.;
+		}
+	}
+}
+
+
+static void render (cairo_t *pCairoContext, CairoDesklet *pDesklet)
+{
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	//g_print ("%s(%x)\n", __func__, pViewportConf);
+	if (pViewportConf == NULL)
+		return ;
+	
+	double fRadius = pViewportConf->iRadius;
+	double fLineWidth = pViewportConf->iLineWidth;
+	// le cadre.
+	cairo_set_line_width (pCairoContext, pViewportConf->iLineWidth);
+	if (pViewportConf->bRoundedRadius)
+	{
+		cairo_translate (pCairoContext, 0., .5 * fLineWidth);
+		cairo_dock_draw_rounded_rectangle (pCairoContext,
+			fRadius,
+			fLineWidth,
+			pDesklet->container.iWidth - 2 * fRadius - fLineWidth,
+			pDesklet->container.iHeight - 2*fLineWidth);
+	}
+	else
+	{
+		cairo_move_to (pCairoContext, 0., 0.);
+		cairo_rel_line_to (pCairoContext,
+			0.,
+			pDesklet->container.iHeight - fRadius - fLineWidth);
+		cairo_rel_line_to (pCairoContext,
+			pViewportConf->iRadius,
+			pViewportConf->iRadius);
+		cairo_rel_line_to (pCairoContext,
+			pDesklet->container.iWidth - fRadius - fLineWidth,
+			0.);
+	}
+	cairo_set_source_rgba (pCairoContext, pViewportConf->fLineColor[0], pViewportConf->fLineColor[1], pViewportConf->fLineColor[2], pViewportConf->fLineColor[3]);
+	cairo_stroke (pCairoContext);
+	
+	// les icones.
+	double w = pDesklet->container.iWidth - 2 * pViewportConf->fMargin;
+	double h = pDesklet->container.iHeight - 2 * pViewportConf->fMargin;
+	int dh = myLabels.iLabelSize;  // taille verticale ajoutee a chaque icone.
+	int dw = 2 * dh;  // taille horizontale ajoutee a chaque icone.
+	if( pViewportConf->iMaxOffsetY == 0 )
+	{
+		dh = (h - pViewportConf->iNbLines * (pViewportConf->iIconSize + myLabels.iLabelSize)) / pViewportConf->iNbLines;  // ecart entre 2 lignes.
+	}
+	if( pViewportConf->iMaxOffsetX == 0 )
+	{
+		dw = (w - pViewportConf->iNbColumns * pViewportConf->iIconSize) / pViewportConf->iNbColumns;  // ecart entre 2 colonnes.
+	}
+	
+	// on determine la 1ere icone a tracer : l'icone suivant l'icone pointee.
+	
+	double x = pViewportConf->fMargin + dw/2, y = pViewportConf->fMargin + dh/2;
+	int q = 0;
+	Icon *pIcon;
+	GList *ic;
+	GList *pVisibleIcons = NULL;
+	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
+	{
+		pIcon = ic->data;
+		if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
+			continue;
+		
+		pIcon->fDrawX = x - pViewportConf->iCurrentOffsetX;
+		pIcon->fDrawY = y - pViewportConf->iCurrentOffsetY;
+		
+		x += pViewportConf->iIconSize + dw;
+		q ++;
+		if (q == pViewportConf->iNbColumns)
+		{
+			q = 0;
+			x = pViewportConf->fMargin + dw/2;
+			y += pViewportConf->iIconSize + myLabels.iLabelSize + dh;
+		}
+		// On ne dessine que les icones qui sont visibles
+		if( pIcon->fDrawX - pViewportConf->fMargin + dw/2 >= 0                &&
+		    pIcon->fDrawY - pViewportConf->fMargin + myLabels.iLabelSize >= 0 &&
+		    pIcon->fDrawX - pViewportConf->fMargin + dw/2 <= w - (pViewportConf->iIconSize + dw)          &&
+		    pIcon->fDrawY - pViewportConf->fMargin + myLabels.iLabelSize <= h - (pViewportConf->iIconSize + myLabels.iLabelSize + dh))
+		{
+			pVisibleIcons = g_list_append(pVisibleIcons, pIcon);
+		}
+	}
+	
+	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pVisibleIcons);
+	if (pFirstDrawnElement == NULL)
+		return;
+	ic = pFirstDrawnElement;
+	do
+	{
+		pIcon = ic->data;
+		if (pIcon->pIconBuffer != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
+		{
+			cairo_save (pCairoContext);
+			
+			cairo_dock_render_one_icon_in_desklet (pIcon, pCairoContext, FALSE, FALSE, pDesklet->container.iWidth);
+			
+			cairo_restore (pCairoContext);
+			
+			
+			if (pIcon->pTextBuffer != NULL)
+			{
+				cairo_save (pCairoContext);
+				cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY);
+				
+				double fOffsetX = 0., fAlpha;
+				if (pIcon->bPointed)
+				{
+					fAlpha = 1.;
+					if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->iTextWidth/2 > pDesklet->container.iWidth)
+						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->iTextWidth/2);
+					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->iTextWidth/2 < 0)
+						fOffsetX = pIcon->iTextWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
+					cairo_set_source_surface (pCairoContext,
+						pIcon->pTextBuffer,
+						fOffsetX + pIcon->fWidth/2 - pIcon->iTextWidth/2,
+						-myLabels.iLabelSize);
+					cairo_paint_with_alpha (pCairoContext, fAlpha);
+				}
+				else
+				{
+					fAlpha = .6;
+					if (pIcon->iTextWidth > pIcon->fWidth + 2 * myLabels.iLabelSize)
+					{
+						fOffsetX = - myLabels.iLabelSize;
+						cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (fOffsetX,
+							0.,
+							fOffsetX + pIcon->fWidth + 2*myLabels.iLabelSize,
+							0.);
+						cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
+						cairo_pattern_add_color_stop_rgba (pGradationPattern,
+							0.,
+							0.,
+							0.,
+							0.,
+							fAlpha);
+						cairo_pattern_add_color_stop_rgba (pGradationPattern,
+							0.75,
+							0.,
+							0.,
+							0.,
+							fAlpha);
+						cairo_pattern_add_color_stop_rgba (pGradationPattern,
+							1.,
+							0.,
+							0.,
+							0.,
+							0.);
+						cairo_set_source_surface (pCairoContext,
+							pIcon->pTextBuffer,
+							fOffsetX,
+							-myLabels.iLabelSize);
+						cairo_mask (pCairoContext, pGradationPattern);
+						cairo_pattern_destroy (pGradationPattern);
+					}
+					else
+					{
+						fOffsetX = pIcon->fWidth/2 - pIcon->iTextWidth/2;
+						cairo_set_source_surface (pCairoContext,
+							pIcon->pTextBuffer,
+							fOffsetX,
+							-myLabels.iLabelSize);
+						cairo_paint_with_alpha (pCairoContext, fAlpha);
+					}
+				}
+				
+				cairo_restore (pCairoContext);
+			}
+		}
+		ic = cairo_dock_get_next_element (ic, pVisibleIcons);
+	}
+	while (ic != pFirstDrawnElement);
+}
+
+
+static void render_opengl (CairoDesklet *pDesklet)
+{
+	CDViewportParameters *pViewportConf = (CDViewportParameters *) pDesklet->pRendererData;
+	if (pViewportConf == NULL)
+		return ;
+	
+	// le cadre.
+	double fRadius = (pViewportConf->bRoundedRadius ? pViewportConf->iRadius : 0.);
+	double fLineWidth = pViewportConf->iLineWidth;
+	if (fLineWidth != 0 && pViewportConf->fLineColor[3] != 0)
+	{
+		cairo_dock_draw_rounded_rectangle_opengl (pDesklet->container.iWidth - 2 * fRadius,
+			pDesklet->container.iHeight,
+			fRadius,
+			fLineWidth,
+			pViewportConf->fLineColor);
+		glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.);
+	}
+	
+	glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.);
+	
+	// les icones.
+	double w = pDesklet->container.iWidth - 2 * pViewportConf->fMargin;
+	double h = pDesklet->container.iHeight - 2 * pViewportConf->fMargin;
+	int dh = myLabels.iLabelSize;  // taille verticale ajoutee a chaque icone.
+	int dw = 2 * dh;  // taille horizontale ajoutee a chaque icone.
+	if( pViewportConf->iMaxOffsetY == 0 )
+	{
+		// ecart entre 2 lignes si il faut repartir vertivalement les icones.
+		dh = (h - pViewportConf->iNbLines * (pViewportConf->iIconSize + myLabels.iLabelSize) - 2*pViewportConf->fMargin - myLabels.iLabelSize) / pViewportConf->iNbLines;
+	}
+	if( pViewportConf->iMaxOffsetX == 0 )
+	{
+		// ecart entre 2 colonnes si il faut repartir horizontalement les icones.
+		dw = (w - pViewportConf->iNbColumns * pViewportConf->iIconSize - 2*pViewportConf->fMargin) / pViewportConf->iNbColumns;
+	}
+	
+	_cairo_dock_enable_texture ();
+	_cairo_dock_set_blend_alpha ();
+	_cairo_dock_set_alpha (1.);
+	
+	
+	double x = pViewportConf->fMargin + dw/2, y = pViewportConf->fMargin + myLabels.iLabelSize + dh/2;
+	int q = 0;
+	Icon *pIcon;
+	GList *ic;
+	GList *pVisibleIcons = NULL;
+	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
+	{
+		pIcon = ic->data;
+		if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
+			continue;
+		
+		pIcon->fDrawX = x - pViewportConf->iCurrentOffsetX;
+		pIcon->fDrawY = y - pViewportConf->iCurrentOffsetY;
+		
+		x += pViewportConf->iIconSize + dw;
+		q ++;
+		if (q == pViewportConf->iNbColumns)
+		{
+			q = 0;
+			x = pViewportConf->fMargin + dw/2;
+			y += pViewportConf->iIconSize + myLabels.iLabelSize + dh;
+		}
+		// On ne dessine que les icones qui sont visibles
+		if( pIcon->fDrawX - pViewportConf->fMargin - dw/2 >= 0                &&
+		    pIcon->fDrawY - pViewportConf->fMargin - myLabels.iLabelSize - dh/2 >= 0 &&
+		    pIcon->fDrawX - pViewportConf->fMargin - dw/2 <= w - (pViewportConf->iIconSize + dw/2)          &&
+		    pIcon->fDrawY - pViewportConf->fMargin - myLabels.iLabelSize - dh/2 <= h - (pViewportConf->iIconSize + myLabels.iLabelSize + dh/2))
+		{
+			pVisibleIcons = g_list_append(pVisibleIcons, pIcon);
+		}
+	}
+	
+	
+	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pVisibleIcons);
+	if (pFirstDrawnElement == NULL)
+		return;
+	ic = pFirstDrawnElement;
+	do
+	{
+		pIcon = ic->data;
+		
+		if (pIcon->iIconTexture != 0 && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
+		{
+			glPushMatrix ();
+			
+			glTranslatef (pIcon->fDrawX + pIcon->fWidth/2,
+				pDesklet->container.iHeight - pIcon->fDrawY - pIcon->fHeight/2,
+				0.);
+			//g_print (" %d) %d;%d %dx%d\n", pIcon->iIconTexture, (int)(pIcon->fDrawX + pIcon->fWidth/2), (int)(pDesklet->container.iHeight - pIcon->fDrawY - pIcon->fHeight/2), (int)(pIcon->fWidth/2), (int)(pIcon->fHeight/2));
+			_cairo_dock_apply_texture_at_size (pIcon->iIconTexture, pIcon->fWidth, pIcon->fHeight);
+			
+			/// generer une notification ...
+			/*if (pIcon->bHasIndicator && g_pIndicatorBuffer.iTexture != 0)
+			{
+				glPushMatrix ();
+				glTranslatef (0., - pIcon->fHeight/2 + g_pIndicatorBuffer.iHeight/2 * pIcon->fWidth / g_pIndicatorBuffer.iWidth, 0.);
+				_cairo_dock_apply_texture_at_size (g_pIndicatorBuffer.iTexture, pIcon->fWidth, g_pIndicatorBuffer.iHeight * pIcon->fWidth / g_pIndicatorBuffer.iWidth);
+				glPopMatrix ();
+			}*/
+			
+			if (pIcon->iLabelTexture != 0)
+			{
+				glPushMatrix ();
+				
+				double dx = .5 * (pIcon->iTextWidth & 1);  // on decale la texture pour la coller sur la grille des coordonnees entieres.
+				double dy = .5 * (pIcon->iTextHeight & 1);
+				double u0 = 0., u1 = 1.;
+				double fOffsetX = 0.;
+				if (pIcon->bPointed)
+				{
+					_cairo_dock_set_alpha (1.);
+					if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->iTextWidth/2 > pDesklet->container.iWidth)
+						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->iTextWidth/2);
+					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->iTextWidth/2 < 0)
+						fOffsetX = pIcon->iTextWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
+				}
+				else
+				{
+					_cairo_dock_set_alpha (.6);
+					if (pIcon->iTextWidth > pIcon->fWidth + 2 * myLabels.iLabelSize)
+					{
+						fOffsetX = 0.;
+						u1 = (double) (pIcon->fWidth + 2 * myLabels.iLabelSize) / pIcon->iTextWidth;
+					}
+				}
+				
+				glTranslatef (ceil (fOffsetX) + dx, ceil (pIcon->fHeight/2 + pIcon->iTextHeight / 2) + dy, 0.);
+				
+				glBindTexture (GL_TEXTURE_2D, pIcon->iLabelTexture);
+				_cairo_dock_apply_current_texture_portion_at_size_with_offset (u0, 0.,
+					u1 - u0, 1.,
+					pIcon->iTextWidth * (u1 - u0), pIcon->iTextHeight,
+					0., 0.);
+				_cairo_dock_set_alpha (1.);
+				
+				glPopMatrix ();
+			}
+			
+			if (pIcon->iQuickInfoTexture != 0)
+			{
+				glTranslatef (0., (- pIcon->fHeight + pIcon->iQuickInfoHeight)/2, 0.);
+				
+				_cairo_dock_apply_texture_at_size (pIcon->iQuickInfoTexture,
+					pIcon->iQuickInfoWidth,
+					pIcon->iQuickInfoHeight);
+			}
+			
+			glPopMatrix ();
+		}
+
+		ic = cairo_dock_get_next_element (ic, pVisibleIcons);
+		
+	} while (ic != pFirstDrawnElement);
+	
+	_cairo_dock_disable_texture ();
+}
+
+
+
+void rendering_register_viewport_desklet_renderer (void)
+{
+	CairoDeskletRenderer *pRenderer = g_new0 (CairoDeskletRenderer, 1);
+	pRenderer->render 			= (CairoDeskletRenderFunc) render;
+	pRenderer->configure 		= (CairoDeskletConfigureRendererFunc) configure;
+	pRenderer->load_data 		= (CairoDeskletLoadRendererDataFunc) load_data;
+	pRenderer->free_data 		= (CairoDeskletFreeRendererDataFunc) free_data;
+	pRenderer->calculate_icons 	= (CairoDeskletCalculateIconsFunc) calculate_icons;
+	pRenderer->render_opengl 	= (CairoDeskletGLRenderFunc) render_opengl;
+	
+	cairo_dock_register_desklet_renderer ("Viewport", pRenderer);
+}

=== added file 'desklet-rendering/src/rendering-desklet-viewport.h'
--- desklet-rendering/src/rendering-desklet-viewport.h	1970-01-01 00:00:00 +0000
+++ desklet-rendering/src/rendering-desklet-viewport.h	2010-07-17 12:02:42 +0000
@@ -0,0 +1,56 @@
+/**
+* This file is a part of the Cairo-Dock project
+*
+* Copyright : (C) see the 'copyright' file.
+* E-mail    : see the 'copyright' file.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 3
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef __RENDERING_DESKLET_VIEWPORT__
+#define  __RENDERING_DESKLET_VIEWPORT__
+
+#include "cairo-dock.h"
+
+
+typedef struct {
+	// from config
+	gboolean bRoundedRadius;
+	gint iRadius;
+	gdouble fLineColor[4];
+	gint iLineWidth;
+	gint iGapBetweenIcons;
+	gint iMinimumIconSize;
+	gboolean bInfiniteWidth;
+	gboolean bInfiniteHeight;
+	// computed data
+	gdouble fMargin;
+	gint iNbIcons;
+	GList* iFirstIconToShow;
+	gint iIconSize;
+	gint iNbLines, iNbColumns;
+	gint iMaxOffsetX;
+	gint iMaxOffsetY;
+	// current state
+	gint iCurrentOffsetX;
+	gint iCurrentOffsetY;
+	gint fCurrentPanXSpeed;
+	gint fCurrentPanYSpeed;
+	} CDViewportParameters;
+
+
+void rendering_register_viewport_desklet_renderer (void);
+
+
+#endif

=== modified file 'desklet-rendering/src/rendering-init.c'
--- desklet-rendering/src/rendering-init.c	2010-07-06 00:03:56 +0000
+++ desklet-rendering/src/rendering-init.c	2010-07-17 12:02:42 +0000
@@ -26,12 +26,13 @@
 //#include "rendering-desklet-controler.h"
 //#include "rendering-desklet-mediaplayer.h"
 #include "rendering-desklet-slide.h"
+#include "rendering-desklet-viewport.h"
 #include "rendering-desklet-decorations.h"
 #include "rendering-init.h"
 
 
 CD_APPLET_DEFINE_BEGIN (N_("desklet rendering"),
-	2,0,0,
+	2,1,0,
 	CAIRO_DOCK_CATEGORY_THEME,
 	N_("This module provides different views for your desklets."),
 	"Fabounet (Fabrice Rey)")
@@ -47,6 +48,7 @@
 	//rendering_register_controler_desklet_renderer ();
 	//rendering_register_mediaplayer_desklet_renderer ();  // By ChAnGFu
 	rendering_register_slide_desklet_renderer ();  // By ChAnGFu
+	rendering_register_viewport_desklet_renderer ();  // By Tofe
 	
 	//\_______________ On enregistre les decorations.
 	cd_rendering_register_desklet_decorations ();


Follow ups