Logo Search packages:      
Sourcecode: cairo-dock-plugins version File versions  Download package

applet-draw.c

/**
* 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/>.
*/

//\________________ Add your name in the copyright file (and / or modify your name here)

#include <cairo-dock.h>
#include <math.h>
#include "applet-struct.h"
#include "applet-rss.h"
#include "applet-draw.h"


void cd_applet_draw_my_desklet (CairoDockModuleInstance *myApplet, int iWidth, int iHeight)
{
      if (iWidth < 20 || iHeight < 20)  // inutile de dessiner tant que le desklet n'a pas atteint sa taille definitive.
            return;
      cd_debug ("%s (%dx%d)", __func__, iWidth, iHeight);
      PangoLayout *pLayout = pango_cairo_create_layout (myDrawContext);
      PangoRectangle ink, log;
      
      // On efface la surface cairo actuelle
      cairo_dock_erase_cairo_context (myDrawContext); 
      
      // dessin du fond (optionnel).
      if (myConfig.bDisplayBackground)
      {
            cairo_save (myDrawContext);
            cairo_translate (myDrawContext,
                        .5*myConfig.iBorderThickness,
                        .5*myConfig.iBorderThickness);            
            cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (0.,
                  0.,
                  0.,
                  iHeight);
            cairo_pattern_add_color_stop_rgba (pGradationPattern,
                  0.,
                  myConfig.fBackgroundColor1[0],
                  myConfig.fBackgroundColor1[1],
                  myConfig.fBackgroundColor1[2],
                  myConfig.fBackgroundColor1[3]);
            cairo_pattern_add_color_stop_rgba (pGradationPattern,
                  1.,
                  myConfig.fBackgroundColor2[0],
                  myConfig.fBackgroundColor2[1],
                  myConfig.fBackgroundColor2[2],
                  myConfig.fBackgroundColor2[3]);
            cairo_set_source (myDrawContext, pGradationPattern);
            
            if (myConfig.iBackgroundRadius != 0)  // On a besoin d'un rayon
            {
                  cairo_dock_draw_rounded_rectangle (myDrawContext,
                        myConfig.iBackgroundRadius,
                        0.,
                        iWidth - myConfig.iBorderThickness - 2 * myConfig.iBackgroundRadius,
                        iHeight - myConfig.iBorderThickness);
            }
            else  // Il ne faut pas de rayon
            {
                  cairo_rectangle (myDrawContext,
                        0., 0.,
                        iWidth - myConfig.iBorderThickness,
                        iHeight - myConfig.iBorderThickness);
            }
            cairo_fill (myDrawContext);
            cairo_pattern_destroy (pGradationPattern);
            cairo_restore (myDrawContext);
      }
      
      int iMargin = .5 * myConfig.iBorderThickness + (1. - sqrt (2) / 2) * myConfig.iBackgroundRadius;  // marge a gauche et au-dessus, pour ne pas mordre sur le coin arrondi.
      double fCurrentY = 0.;  // position de la ligne courante.
      double fTitleWidth = 0., fTitleHeight = 0.;
      int iTitleX = 0;
      
      // On charge le logo si besoin
      PangoFontDescription *fd = pango_font_description_from_string (myConfig.cTitleFont);
      pango_layout_set_font_description (pLayout, fd);
      gboolean bLogoIsOn = FALSE;  // utile pour decaler le texte du titre
      if (myConfig.bDisplayLogo)
      {
            // on recupere la taille du titre.
            int iSize = pango_font_description_get_size (fd);
            if (!pango_font_description_get_size_is_absolute (fd))
                  iSize /= PANGO_SCALE;
            if (iSize == 0)
                  iSize = 16;
            
            // on en deduit la taille du logo.
            double fLogoSize = MIN (iWidth/2, MIN (iHeight/2, myConfig.fLogoSize * iSize));  // on le limite un peu.
            if (fLogoSize < 1)
                  fLogoSize = 1;
            cd_debug ("  fLogoSize  :%.2f", fLogoSize);
            
            // on cree la surface du logo si necessaire.
            if (myData.fLogoSize != iSize || myData.pLogoSurface == NULL)
            {
                  cairo_surface_destroy (myData.pLogoSurface);
                  myData.fLogoSize = fLogoSize;
                  myData.pLogoSurface = cairo_dock_create_surface_for_icon (myConfig.cLogoPath,
                        myDrawContext,
                        fLogoSize,
                        fLogoSize);
            }
            
            // on affiche le logo.
            if (myData.pLogoSurface != NULL)
            {
                  bLogoIsOn = TRUE;
                  fTitleWidth = myData.fLogoSize + 5;  // 5 pixels d'ecart entre le logo et le texte.
                  iTitleX = MAX (0, myConfig.fTitleAlignment * (iWidth - myConfig.iBorderThickness - 2*iMargin - fTitleWidth));
            }
      }
      pango_font_description_free (fd);
      
      // dessin du texte.
      if (myData.pItemList != NULL)
      {
            GList *it = myData.pItemList;
            CDRssItem *pItem = it->data;
            
            // dessin du nom du flux.
            if (pItem->cTitle != NULL)
            {
                  pango_layout_set_text (pLayout, pItem->cTitle, -1);
                  pango_layout_get_pixel_extents (pLayout, &ink, &log);
                  
                  fTitleWidth += log.width;
                  iTitleX = MAX (0, myConfig.fTitleAlignment * (iWidth - myConfig.iBorderThickness - 2*iMargin - fTitleWidth));
                  fTitleHeight = log.height;
                  
                  cairo_set_source_rgba (myDrawContext, myConfig.fTitleTextColor[0], myConfig.fTitleTextColor[1], myConfig.fTitleTextColor[2], myConfig.fTitleTextColor[3]);
                  
                  cairo_move_to (myDrawContext,
                        iMargin + iTitleX + (bLogoIsOn ? myData.fLogoSize + 5 : 0),
                        iMargin + (bLogoIsOn ? MAX (0, (myData.fLogoSize - fTitleHeight)/2) : 0));
                  pango_cairo_show_layout (myDrawContext, pLayout);
                  
                  fCurrentY = iMargin + MAX (log.height, (bLogoIsOn ? myData.fLogoSize : 0)) + myConfig.iSpaceBetweenFeedLines;
            }
            
            // dessin des lignes.
            fd = pango_font_description_from_string (myConfig.cFont);
            pango_layout_set_font_description (pLayout, fd);
            pango_font_description_free (fd);
            
            cairo_set_source_rgba (myDrawContext, myConfig.fTextColor[0], myConfig.fTextColor[1], myConfig.fTextColor[2], myConfig.fTextColor[3]);
            
            if (myData.iFirstDisplayedItem > 0)
            {
                  it = g_list_nth (it, myData.iFirstDisplayedItem);
                  if (it == NULL)
                  {
                        it = g_list_last (myData.pItemList);
                        if (it->prev)
                              it = it->prev;
                  }
            }
            
            for (it = it->next; it != NULL; it = it->next)
            {
                  pItem = it->data;
                  if (pItem->cTitle == NULL)
                        continue;
                  
                  gchar *cLine = g_strdup (pItem->cTitle);
                  cd_rssreader_cut_line (cLine, pLayout, iWidth - myConfig.iBorderThickness - 2*iMargin - myConfig.iTextMargin);
                  
                  pango_layout_set_text (pLayout, cLine, -1);
                  pango_layout_get_pixel_extents (pLayout, &ink, &log);
                  
                  if (fCurrentY + log.height > iHeight - iMargin - .5*myConfig.iBorderThickness)  // on deborde en hauteur.
                  {
                        //g_print ("fCurrentY : %.1f + %d > %.1f\n", fCurrentY, log.height, iHeight - iMargin - .5*myConfig.iBorderThickness);
                        gchar *rc;
                        do
                        {
                              rc = strrchr (cLine, '\n');  // pas tres optimise mais pratique.
                              if (!rc)
                                    break;
                              *rc = '\0';
                              pango_layout_set_text (pLayout, cLine, -1);
                              pango_layout_get_pixel_extents (pLayout, &ink, &log);
                              //g_print ("%s -> : %.1f + %d / %.1f\n", cLine, fCurrentY, log.height, iHeight - iMargin - .5*myConfig.iBorderThickness);
                        } while (fCurrentY + log.height > iHeight - iMargin - .5*myConfig.iBorderThickness);
                        
                        if (fCurrentY + log.height > iHeight - iMargin - .5*myConfig.iBorderThickness)  // on deborde toujours => on quitte.
                        {
                              g_free (cLine);
                              break;
                        }
                        else  // on a reussi a en afficher une partie, on le signale avec des '...'.
                        {
                              gchar *cCutLine = g_strdup_printf ("%s...", cLine);
                              pango_layout_set_text (pLayout, cCutLine, -1);
                              pango_layout_get_pixel_extents (pLayout, &ink, &log);
                              if (log.width > iWidth - myConfig.iBorderThickness - 2*iMargin - myConfig.iTextMargin)  // les "..." font deborder
                              {
                                    g_free (cCutLine);
                                    gchar *sp = strrchr (cLine, ' ');
                                    if (sp)  // on remplace le dernier mot par les "..."
                                    {
                                          *sp = '.';
                                          *(sp+1) = '.';
                                          *(sp+2) = '.';
                                          *(sp+3) = '\0';
                                          cCutLine = NULL;
                                    }
                                    else  // on coupe le dernier mot par les "..."
                                          cCutLine = cairo_dock_cut_string (cLine, -3);
                                    pango_layout_set_text (pLayout, cCutLine ? cCutLine : cLine, -1);
                                    pango_layout_get_pixel_extents (pLayout, &ink, &log);
                              }
                              g_free (cCutLine);
                        }
                  }
                  
                  g_free (cLine);
                  
                  cairo_move_to (myDrawContext,
                        iMargin + myConfig.iTextMargin,
                        fCurrentY);
                  pango_cairo_show_layout (myDrawContext, pLayout);
                  
                  fCurrentY += log.height + myConfig.iSpaceBetweenFeedLines;
                  //g_print ("fCurrentY <- %.2f\n", fCurrentY);
            }
      }
      
      // dessin du logo.
      if (bLogoIsOn)
      {
            cairo_set_source_surface (myDrawContext,
                  myData.pLogoSurface,
                  iMargin + iTitleX,
                  iMargin + MAX (0, (fTitleHeight - myData.fLogoSize)/2));
            cairo_paint (myDrawContext);
      }
      
      // dessin du cadre (optionnel).
      if (myConfig.bDisplayBackground)
      {
            cairo_save (myDrawContext);
            cairo_set_source_rgba (myDrawContext,
                  myConfig.fBorderColor[0],
                  myConfig.fBorderColor[1],
                  myConfig.fBorderColor[2],
                  myConfig.fBorderColor[3]);
            cairo_set_line_width (myDrawContext, myConfig.iBorderThickness);
            cairo_translate (myDrawContext,
                  .5*myConfig.iBorderThickness,
                  .5*myConfig.iBorderThickness);
            cairo_dock_draw_rounded_rectangle (myDrawContext,
                  myConfig.iBackgroundRadius,
                  0.,
                  iWidth - 2*myConfig.iBackgroundRadius - myConfig.iBorderThickness,
                  iHeight - myConfig.iBorderThickness);
            cairo_stroke (myDrawContext);
            cairo_restore (myDrawContext);
      }
      
      g_object_unref (pLayout);
      
      // on met a jour la texture OpenGL.
      if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
      {
            cairo_dock_update_icon_texture (myIcon);
      }
}


void cd_applet_update_my_icon (CairoDockModuleInstance *myApplet)
{
      if (myDesklet)
      {
            // taille de la texture.
            int iWidth, iHeight;
            CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
            
            cd_applet_draw_my_desklet (myApplet, iWidth, iHeight);            
            
            CD_APPLET_REDRAW_MY_ICON;
      }
}

Generated by  Doxygen 1.6.0   Back to index