static Icon *cd_calculate_icons (CairoDock *pDock) { //\_____________ On calcule le nombre de groupes et la place qu'ils occupent. int iNbGroups = 1; double fCurrentGroupWidth = - myIconsParam.iIconGap, fGroupsWidth = 0.; double fSeparatorsPonderation = 0; GList *ic; Icon *pIcon; for (ic = pDock->icons; ic != NULL; ic = ic->next) { pIcon = ic->data; if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon)) { pIcon->fScale = 1.; if (pIcon->fInsertRemoveFactor != 0) { if (pIcon->fInsertRemoveFactor > 0) pIcon->fScale *= pIcon->fInsertRemoveFactor; else pIcon->fScale *= (1 + pIcon->fInsertRemoveFactor); } if (fCurrentGroupWidth > 0) // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote ou un au debut. { iNbGroups ++; fSeparatorsPonderation += pIcon->fScale; fGroupsWidth += MAX (0, fCurrentGroupWidth); fCurrentGroupWidth = - myIconsParam.iIconGap; } continue; } pIcon->fScale = 1.; if (pIcon->fInsertRemoveFactor != 0) { if (pIcon->fInsertRemoveFactor > 0) pIcon->fScale *= pIcon->fInsertRemoveFactor; else pIcon->fScale *= (1 + pIcon->fInsertRemoveFactor); } fCurrentGroupWidth += pIcon->fWidth * pIcon->fScale + myIconsParam.iIconGap; } if (fCurrentGroupWidth > 0) // le groupe courant est non vide, sinon c'est juste un separateur a la fin. { fGroupsWidth += fCurrentGroupWidth; } else iNbGroups --; if (fGroupsWidth < 0) fGroupsWidth = 0; //\_____________ On en deduit l'ecart entre les groupes d'icones. double W = cairo_dock_get_max_authorized_dock_width (pDock); double fScreenBorderGap = myDocksParam.iDockRadius + myDocksParam.iDockLineWidth; // on laisse un ecart avec le bord de l'ecran. double fGroupGap; if (iNbGroups > 1) { fGroupGap = (W - 2*fScreenBorderGap - fGroupsWidth) / (iNbGroups - 1); if (fSeparatorsPonderation != 0 && iNbGroups > 2) fGroupGap /= fSeparatorsPonderation / (iNbGroups - 1); } else fGroupGap = W - fScreenBorderGap - fGroupsWidth; //\_____________ On determine la position de chaque icone. Icon *pPointedIcon = NULL; double xm = pDock->container.iMouseX; double xg = fScreenBorderGap; // abscisse de l'icone courante, et abscisse du debut du groupe courant. if (iNbGroups <= 1) // if only 1 group, there is no separator that will expand icons => we use the alignment to place them. xg = pDock->fAlign * (W - fGroupsWidth) + 2 * fScreenBorderGap * (.5 - pDock->fAlign); double x = xg; fCurrentGroupWidth = - myIconsParam.iIconGap; for (ic = pDock->icons; ic != NULL; ic = ic->next) { pIcon = ic->data; if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon)) { pIcon->fX = x; pIcon->fDrawX = pIcon->fX; if (pDock->container.bDirectionUp) pIcon->fY = pDock->iMaxDockHeight - pDock->iMinDockHeight; else pIcon->fY = pDock->iMinDockHeight; pIcon->fDrawY = pIcon->fY; pIcon->fWidthFactor = 0; if (fCurrentGroupWidth > 0) // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote. { xg += fCurrentGroupWidth + fGroupGap * pIcon->fScale; if (pPointedIcon == NULL && xm > x && xm < xg) { pIcon->bPointed = TRUE; pPointedIcon = pIcon; } else pIcon->bPointed = FALSE; x = xg; fCurrentGroupWidth = - myIconsParam.iIconGap; } continue; } fCurrentGroupWidth += pIcon->fWidth * pIcon->fScale + myIconsParam.iIconGap; pIcon->fX = x; if (pPointedIcon == NULL && xm > pIcon->fX - .5*myIconsParam.iIconGap && xm <= pIcon->fX + pIcon->fWidth * pIcon->fScale + .5*myIconsParam.iIconGap) { pIcon->bPointed = TRUE; pPointedIcon = pIcon; } else pIcon->bPointed = FALSE; pIcon->fDrawX = pIcon->fX; if (pDock->container.bDirectionUp) pIcon->fY = pDock->iMaxDockHeight - (myDocksParam.iDockLineWidth + myDocksParam.iFrameMargin + pIcon->fHeight); else pIcon->fY = myDocksParam.iDockLineWidth + myDocksParam.iFrameMargin; pIcon->fDrawY = pIcon->fY; pIcon->fWidthFactor = 1.; pIcon->fHeightFactor = 1.; pIcon->fOrientation = 0.; pIcon->fAlpha = 1.; x += pIcon->fWidth * pIcon->fScale + myIconsParam.iIconGap; } cairo_dock_check_if_mouse_inside_linear (pDock); cairo_dock_check_can_drop_linear (pDock); return pPointedIcon; }
void cd_rendering_calculate_max_dock_size_3D_plane (CairoDock *pDock) { pDock->pFirstDrawnElement = cairo_dock_calculate_icons_positions_at_rest_linear (pDock->icons, pDock->fFlatDockWidth, pDock->iScrollOffset); //pDock->iMaxDockHeight = (int) ((1 + g_fAmplitude) * pDock->iMaxIconHeight + myIcons.fReflectSize * pDock->fRatio) + myLabels.iLabelSize + myBackground.iDockLineWidth + myBackground.iFrameMargin; _define_parameters (hi, h0, H, l, r, gamma, h, w, dw); pDock->iMaxDockHeight = (int) (hi + h0max + l); // 1ere estimation. // w w = ceil (cairo_dock_calculate_max_dock_width (pDock, pDock->pFirstDrawnElement, pDock->fFlatDockWidth, 1., 2 * dw)); // pDock->iMaxDockWidth // -> gamma gamma = w / 2 / H; // -> h h = hi + h0 / (1 + gamma); // en fait, sqrt (1 + gamma * gamma), mais on simplifie pour diminuer l'ordre de 2. pDock->iDecorationsHeight // -> dw dw = h * gamma + r + (l+(r==0)*2)*sqrt(1+gamma*gamma); // en fait, h*gamma + r*(1-sin)/cos, or (1-sin)/cos <= 1, on majore pour simplifier. on aurait r + gamma * (h - 2 * r) si on utilisait des cercles au lieu de courbes de Bezier. double Ws = w+2*dw; double W = Ws - 2 * (r + (l+(r==0)*2)*sqrt(1+gamma*gamma)); double a = H + hi; double b = H + hi + h0 - W / 2; double c = - W / 2; double g = (-b + sqrt (b * b - 4 * a * c)) / 2 / a; g_print ("gamma : %f (=) %f\n", gamma, g); if (cairo_dock_is_extended_dock (pDock)) // mode panel etendu. { double Ws = cairo_dock_get_max_authorized_dock_width (pDock); if (w + 2 * dw < Ws) // alors on etend. { double extra = Ws - w; pDock->iMaxDockWidth = ceil (cairo_dock_calculate_max_dock_width (pDock, pDock->pFirstDrawnElement, pDock->fFlatDockWidth, 1., extra)); // on pourra optimiser, ce qui nous interesse ici c'est les fXMin/fXMax. double W = Ws - 2 * (r + (l+(r==0)*2)*sqrt(1+gamma*gamma)); double a = H + hi; double b = H + hi + h0 - W / 2; double c = - W / 2; gamma = (-b + sqrt (b * b - 4 * a * c)) / 2 / a; g_print ("mode etendu : pDock->iMaxDockWidth : %d, gamma = %f\n", pDock->iMaxDockWidth, gamma); h = hi + h0 / (1 + gamma); } } else // rien d'autre a faire { pDock->iMaxDockWidth = ceil (cairo_dock_calculate_max_dock_width (pDock, pDock->pFirstDrawnElement, pDock->fFlatDockWidth, 1., 2 * dw)); // on pourra optimiser, ce qui nous interesse ici c'est les fXMin/fXMax. } pDock->iDecorationsHeight = h; g_print ("h : %.2f -> %d\n", h, pDock->iDecorationsHeight); pDock->iDecorationsWidth = pDock->iMaxDockWidth; // taille min. pDock->iMinDockHeight = myBackground.iDockLineWidth + myBackground.iFrameMargin + myIcons.fReflectSize * pDock->fRatio + pDock->iMaxIconHeight; double gamma_min = pDock->fFlatDockWidth / 2 / H; double dw_min = h * gamma_min + r + (l+(r==0)*2)*sqrt(1+gamma_min*gamma_min); //cairo_dock_calculate_extra_width_for_trapeze (pDock->iDecorationsHeight, fInclination, myBackground.iDockRadius, myBackground.iDockLineWidth); if (cairo_dock_is_extended_dock (pDock)) // mode panel etendu. { pDock->iMinDockWidth = cairo_dock_get_max_authorized_dock_width (pDock); } else { pDock->iMinDockWidth = pDock->fFlatDockWidth + 2 * dw_min; } // on reboucle (sauf que on reboucle pas). //fInclination = 0.5 * pDock->iMinDockWidth / iVanishingPointY; //fExtraWidthMin = cairo_dock_calculate_extra_width_for_trapeze (pDock->iDecorationsHeight, fInclination, myBackground.iDockRadius, myBackground.iDockLineWidth); //pDock->iMinDockWidth = pDock->fFlatDockWidth + fExtraWidthMin; // en commentaire depuis des lustres. pDock->iMinLeftMargin = dw; pDock->iMinRightMargin = dw; Icon *pFirstIcon = cairo_dock_get_first_icon (pDock->icons); if (pFirstIcon != NULL) pDock->iMaxRightMargin = dw + pFirstIcon->fWidth; Icon *pLastIcon = cairo_dock_get_last_icon (pDock->icons); if (pLastIcon != NULL) pDock->iMaxRightMargin = dw + pLastIcon->fWidth; pDock->inputArea.x = (pDock->iMinDockWidth - pDock->fFlatDockWidth) / 2; pDock->inputArea.y = 0; pDock->inputArea.width = pDock->fFlatDockWidth; pDock->inputArea.height = pDock->iMinDockHeight; g_print ("input area : %d + %d\n", pDock->inputArea.x, pDock->inputArea.width); // on charge les separateurs plat. if (my_pFlatSeparatorSurface[0] == NULL && my_iFlatSeparatorTexture == 0 && my_iDrawSeparator3D == CD_FLAT_SEPARATOR) cd_rendering_load_flat_separator (CAIRO_CONTAINER (g_pMainDock)); }
static void cd_compute_size (CairoDock *pDock) { //\_____________ On calcule le nombre de groupes et la place qu'ils occupent. int iNbGroups = 1; double fCurrentGroupWidth = - myIconsParam.iIconGap, fGroupsWidth = 0.; GList *ic; Icon *pIcon; for (ic = pDock->icons; ic != NULL; ic = ic->next) { pIcon = ic->data; if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon)) { if (fCurrentGroupWidth > 0) // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote ou un au debut. { iNbGroups ++; fGroupsWidth += fCurrentGroupWidth; //g_print ("fGroupsWidth += %.2f\n", fCurrentGroupWidth); fCurrentGroupWidth = - myIconsParam.iIconGap; } continue; } fCurrentGroupWidth += pIcon->fWidth + myIconsParam.iIconGap; //g_print ("fCurrentGroupWidth <- %.2f\n", fCurrentGroupWidth); } if (fCurrentGroupWidth > 0) // le groupe courant est non vide, sinon c'est juste un separateur a la fin. { fGroupsWidth += MAX (0, fCurrentGroupWidth); //g_print ("fGroupsWidth += %.2f\n", fCurrentGroupWidth); } else iNbGroups --; if (fGroupsWidth < 0) fGroupsWidth = 0; //\_____________ On en deduit l'ecart entre les groupes d'icones. double W = cairo_dock_get_max_authorized_dock_width (pDock); double fScreenBorderGap = myDocksParam.iDockRadius + myDocksParam.iDockLineWidth; // on laisse un ecart avec le bord de l'ecran. double fGroupGap = (iNbGroups > 1 ? (W - 2*fScreenBorderGap - fGroupsWidth) / (iNbGroups - 1) : W - fScreenBorderGap - fGroupsWidth); if (fGroupGap < myIconsParam.iIconGap) // les icones depassent en largeur. fGroupGap = myIconsParam.iIconGap; //g_print (" -> %d groups, %d/%d\nfGroupGap = %.2f\n", iNbGroups, (int)fGroupsWidth, (int)W, fGroupGap); //\_____________ On calcule la position au repos des icones et la taille du dock. double xg = fScreenBorderGap; // abscisse de l'icone courante, et abscisse du debut du groupe courant. double x = xg; fCurrentGroupWidth = - myIconsParam.iIconGap; for (ic = pDock->icons; ic != NULL; ic = ic->next) { pIcon = ic->data; if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon)) { pIcon->fXAtRest = x; //g_print ("*** separator at %d\n", (int)x); if (fCurrentGroupWidth > 0) // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote. { xg += fCurrentGroupWidth + fGroupGap; x = xg; //g_print ("jump to %.2f\n", x); fCurrentGroupWidth = - myIconsParam.iIconGap; } continue; } fCurrentGroupWidth += pIcon->fWidth + myIconsParam.iIconGap; pIcon->fXAtRest = x; x += pIcon->fWidth + myIconsParam.iIconGap; } pDock->fMagnitudeMax = 0.; // pas de vague. double hicon = pDock->iMaxIconHeight; pDock->iDecorationsHeight = hicon * pDock->container.fRatio + 2 * myDocksParam.iFrameMargin; pDock->iMaxDockWidth = pDock->fFlatDockWidth = pDock->iMinDockWidth = MAX (W, x); // if > W, we'll come back here with a smaller ratio. //g_print ("iMaxDockWidth : %d (%.2f)\n", pDock->iMaxDockWidth, pDock->container.fRatio); pDock->iMaxDockHeight = myDocksParam.iDockLineWidth + myDocksParam.iFrameMargin + hicon * pDock->container.fRatio + myDocksParam.iFrameMargin + myDocksParam.iDockLineWidth + (pDock->container.bIsHorizontal ? myIconsParam.iLabelSize : 0); pDock->iMaxDockHeight = MAX (pDock->iMaxDockHeight, pDock->iMaxIconHeight * (1 + myIconsParam.fAmplitude)); // au moins la taille du FBO. //g_print ("panel view: pDock->iMaxIconHeight = %d\n", pDock->iMaxIconHeight); pDock->iDecorationsWidth = pDock->iMaxDockWidth; pDock->iMinDockHeight = 2 * (myDocksParam.iDockLineWidth + myDocksParam.iFrameMargin) + hicon * pDock->container.fRatio; /// TODO: make the height constant, to avoid moving all windows when space is reserved and ratio changes. pDock->iActiveWidth = pDock->iMaxDockWidth; pDock->iActiveHeight = pDock->iMinDockHeight; if (! pDock->container.bIsHorizontal) pDock->iMaxDockHeight += 8*myIconsParam.iLabelSize; // vertical dock, add some padding to draw the labels CDPanelData *pData = pDock->pRendererData; if (pData == NULL) { pData = g_new0 (CDPanelData, 1); pDock->pRendererData = pData; } pData->fGroupGap = fGroupGap; }