Ejemplo n.º 1
0
// Update desired size of the button. If the size changes, trigger layout
// (which will in turn request repaints of affected areas)
// To keep size of the button stable (to avoid re-layouts) we use font
// line spacing to be the height of the button, even if text is empty.
// Note: it might be that for some cases button with no text should collapse
// in size but we don't have a need for that yet
void Button::RecalculateSize(bool repaintIfSizeDidntChange)
{
    Size prevSize = desiredSize;

    desiredSize = GetBorderAndPaddingSize(cachedStyle);
    Graphics *gfx = AllocGraphicsForMeasureText();
    CachedStyle *s = cachedStyle;
    Font *font = GetCachedFont(s->fontName, s->fontSize, s->fontWeight);

    textDx = 0;
    float fontDy = font->GetHeight(gfx);
    RectF bbox;
    if (text) {
        bbox = MeasureText(gfx, font, text);
        textDx = (size_t)bbox.Width; // TODO: round up?
        // bbox shouldn't be bigger than fontDy. We apply magic adjustment because
        // bbox is bigger in n-th decimal point
        CrashIf(fontDy + .5f < bbox.Height);
    }
    desiredSize.Width  += textDx;
    desiredSize.Height += (INT)fontDy; // TODO: round up?
    FreeGraphicsForMeasureText(gfx);

    if (!prevSize.Equals(desiredSize))
        RequestLayout(this);
    else if (repaintIfSizeDidntChange)
        RequestRepaint(this);
}
Ejemplo n.º 2
0
// TODO: the position still seems a bit off wrt. padding
void ButtonVector::RecalculateSize(bool repaintIfSizeDidntChange)
{
    Size prevSize = desiredSize;

    CachedStyle *s = cachedStyle;
    desiredSize = GetBorderAndPaddingSize(s);

    Rect bbox;
    Brush *brStroke = BrushFromColorData(s->stroke, bbox);
    if (0.f == s->strokeWidth) {
        graphicsPath->GetBounds(&bbox);
    } else {
        Pen pen(brStroke, s->strokeWidth);
        // pen widith is multiplied by MiterLimit(), which is 10 by default
        // so set it explicitly to 1 for the size we expect
        pen.SetMiterLimit(1.f);
        pen.SetAlignment(PenAlignmentInset);
        graphicsPath->GetBounds(&bbox, NULL, &pen);
    }
    desiredSize.Width  += bbox.Width;
    desiredSize.Height += bbox.Height;

    if (!prevSize.Equals(desiredSize))
        RequestLayout(this);
    else if (repaintIfSizeDidntChange)
        RequestRepaint(this);
}
Ejemplo n.º 3
0
void ButtonVector::Paint(Graphics *gfx, int offX, int offY)
{
    if (!IsVisible())
        return;

    CachedStyle *s = cachedStyle;

    RectF bbox((REAL)offX, (REAL)offY, (REAL)pos.Width, (REAL)pos.Height);
    Brush *brBgColor = BrushFromColorData(s->bgColor, bbox);
    gfx->FillRectangle(brBgColor, bbox);

    Rect r(offX, offY, pos.Width, pos.Height);
    DrawBorder(gfx, r, s);
    if (!graphicsPath)
        return;

    // graphicsPath bbox can have non-zero X,Y
    Rect gpBbox;
    Brush *brFill = BrushFromColorData(s->fill, bbox);
    Brush *brStroke = BrushFromColorData(s->stroke, bbox);
    Pen pen(brStroke, s->strokeWidth);
    pen.SetMiterLimit(1.f);
    pen.SetAlignment(PenAlignmentInset);
    if (0.f == s->strokeWidth)
        graphicsPath->GetBounds(&gpBbox);
    else
        graphicsPath->GetBounds(&gpBbox, NULL, &pen);

    // calculate the position of graphics path within given button position, size
    // and desired vertical/horizontal alignment.
    // Note: alignment is calculated against the size after substracting 
    // ncSize is the size of the non-client parts i.e. border and padding, on both sides
    Size ncSize = GetBorderAndPaddingSize(s);
    int elOffY = s->vertAlign.CalcOffset( gpBbox.Height, pos.Height - ncSize.Height);
    int elOffX = s->horizAlign.CalcOffset(gpBbox.Width,  pos.Width  - ncSize.Width );

    int x = offX + elOffX + s->padding.left + (int)s->borderWidth.left + gpBbox.X;
    int y = offY + elOffY + s->padding.top  + (int)s->borderWidth.top  + gpBbox.Y;

    // TODO: can I avoid making a copy of GraphicsPath?
    GraphicsPath *tmp = graphicsPath->Clone();
    Matrix m;
    m.Translate((float)x, (float)y);
    tmp->Transform(&m);
    gfx->FillPath(brFill, tmp);
    if (0.f != s->strokeWidth)
        gfx->DrawPath(&pen, tmp);
}
Ejemplo n.º 4
0
// Update desired size of the button. If the size changes, trigger layout
// (which will in turn request repaints of affected areas)
// To keep size of the button stable (to avoid re-layouts) we use font
// line spacing to be the height of the button, even if text is empty.
// Note: it might be that for some cases button with no text should collapse
// in size but we don't have a need for that yet
void Button::RecalculateSize(bool repaintIfSizeDidntChange)
{
    Size prevSize = desiredSize;

    desiredSize = GetBorderAndPaddingSize(cachedStyle);
    Graphics *gfx = AllocGraphicsForMeasureText();
    CachedStyle *s = cachedStyle;
    Font *font = GetCachedFont(s->fontName, s->fontSize, s->fontWeight);

    textDx = 0;
    float fontDy = font->GetHeight(gfx);
    RectF bbox;
    if (text) {
        bbox = MeasureText(gfx, font, text);
        textDx = CeilI(bbox.Width);
        // I theorize that bbox shouldn't be bigger than fontDy. However, in practice
        // it is (e.g. for Lucida Grande and text "Page: 0 / 0", bbox.Dy is 19.00
        // and fontDy is 18.11). I still want to know if the difference gets even bigger
        // than that
        float maxDiff = 1.f;
        if (bbox.Height > fontDy + maxDiff) {
            fontDy = bbox.Height;
            float diff = fontDy + maxDiff - bbox.Height;
            char *fontName = str::conv::ToUtf8(s->fontName);
            char *tmp = str::conv::ToUtf8(text);
            CrashLogFmt("fontDy=%.2f, bbox.Height=%.2f, diff=%.2f (should be > 0) font: %s, text='%s'\r\n", (float)fontDy, (float)bbox.Height, diff, fontName, tmp);
            CrashIf(diff < 0);
        }
    }
    desiredSize.Width  += textDx;
    desiredSize.Height += CeilI(fontDy);
    FreeGraphicsForMeasureText(gfx);

    if (!prevSize.Equals(desiredSize))
        RequestLayout(this);
    else if (repaintIfSizeDidntChange)
        RequestRepaint(this);
}
Ejemplo n.º 5
0
Size Grid::Measure(const Size availableSize) {
    RebuildCellDataIfNeeded();

    Size borderSize(GetBorderAndPaddingSize(cachedStyle));

    Cell* cell;
    Control* el;
    for (Grid::CellData& d : els) {
        cell = GetCell(d.row, d.col);
        cell->desiredSize.Width = 0;
        cell->desiredSize.Height = 0;
        el = d.el;
        if (!el->IsVisible())
            continue;

        // calculate max dx of each column (dx of widest cell in the row)
        //  and max dy of each row (dy of tallest cell in the column)
        el->Measure(availableSize);

        // TODO: take cell's border and padding into account

        cell->desiredSize = el->DesiredSize();
        // if a cell spans multiple columns, we don't count its size here
        if (d.colSpan == 1) {
            if (cell->desiredSize.Width > maxColWidth[d.col])
                maxColWidth[d.col] = cell->desiredSize.Width;
        }
        if (cell->desiredSize.Height > maxRowHeight[d.row])
            maxRowHeight[d.row] = cell->desiredSize.Height;
    }

    // account for cells with colSpan > 1. If cell.dx > total dx
    // of columns it spans, we widen the columns by equally
    // re-distributing the difference among columns
    for (Grid::CellData& d : els) {
        if (d.colSpan == 1)
            continue;
        cell = GetCell(d.row, d.col);

        int totalDx = 0;
        for (int i = d.col; i < d.col + d.colSpan; i++) {
            totalDx += maxColWidth[i];
        }
        int diff = cell->desiredSize.Width - totalDx;
        if (diff > 0) {
            int diffPerCol = diff / d.colSpan;
            int rest = diff % d.colSpan;
            // note: we could try to redistribute rest for ideal sizing instead of
            // over-sizing but not sure if that would matter in practice
            if (rest > 0)
                diffPerCol += 1;
            CrashIf(diffPerCol * d.colSpan < diff);
            for (int i = d.col; i < d.col + d.colSpan; i++) {
                maxColWidth[i] += diffPerCol;
            }
        }
    }

    int desiredWidth = 0;
    int desiredHeight = 0;
    for (int row = 0; row < rows; row++) {
        desiredHeight += maxRowHeight[row];
    }
    for (int col = 0; col < cols; col++) {
        desiredWidth += maxColWidth[col];
    }
    // TODO: what to do if desired size is more than availableSize?
    desiredSize.Width = desiredWidth + borderSize.Width;
    desiredSize.Height = desiredHeight + borderSize.Height;
    return desiredSize;
}