Skip to content

Commit

Permalink
libappfw|LabelWidget: Added overlay image drawing for labels
Browse files Browse the repository at this point in the history
The "separate alignment" mode turned out to be infeasible, because
when used, the label should be manually sized rather than using
an expanding policy. This would have complicated the internal logic
of the widget too much.

Now labels can have a simple overlay image drawn on top.
  • Loading branch information
skyjake committed Feb 25, 2014
1 parent 7ad27d3 commit 7072dc9
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 59 deletions.
12 changes: 10 additions & 2 deletions doomsday/libappfw/include/de/widgets/labelwidget.h
Expand Up @@ -80,6 +80,15 @@ class LIBAPPFW_PUBLIC LabelWidget : public GuiWidget
*/
void setImage(ProceduralImage *procImage);

/**
* Sets an overlay image that gets drawn over the label contents.
*
* @param overlayProcImage Procedural image. LabelWidget takes ownership.
* @param alignment Alignment for the overlaid image.
*/
void setOverlayImage(ProceduralImage *overlayProcImage,
ui::Alignment const &alignment = ui::AlignCenter);

String text() const;

/**
Expand All @@ -97,8 +106,7 @@ class LIBAPPFW_PUBLIC LabelWidget : public GuiWidget
enum AlignmentMode {
AlignByCombination,
AlignOnlyByImage,
AlignOnlyByText,
AlignSeparately ///< Aligned separately within the entire content rectangle.
AlignOnlyByText
};

/**
Expand Down
131 changes: 74 additions & 57 deletions doomsday/libappfw/src/widgets/labelwidget.cpp
Expand Up @@ -40,6 +40,7 @@ public Font::RichFormat::IStyle
Alignment textAlign;
Alignment lineAlign;
Alignment imageAlign;
Alignment overlayAlign;
ContentFit imageFit;
Vector2f overrideImageSize;
float imageScale;
Expand Down Expand Up @@ -68,6 +69,7 @@ public Font::RichFormat::IStyle
mutable Vector2ui latestTextSize;

QScopedPointer<ProceduralImage> image;
QScopedPointer<ProceduralImage> overlayImage;
Drawable drawable;
GLUniform uMvpMatrix;
GLUniform uColor;
Expand Down Expand Up @@ -186,6 +188,11 @@ public Font::RichFormat::IStyle
{
image->glInit();
}

if(!overlayImage.isNull())
{
overlayImage->glInit();
}
}

void glDeinit()
Expand All @@ -196,11 +203,15 @@ public Font::RichFormat::IStyle
{
image->glDeinit();
}
if(!overlayImage.isNull())
{
overlayImage->glDeinit();
}
}

bool hasImage() const
{
return !image.isNull();
return !image.isNull() && image->size() != ProceduralImage::Size(0, 0);
}

bool hasText() const
Expand All @@ -226,14 +237,19 @@ public Font::RichFormat::IStyle
return latestTextSize;
}

Rectanglei contentArea() const
{
return self.rule().recti().adjusted(margin.xy(), -margin.zw());
}

/**
* Determines where the label's image and text should be drawn.
*
* @param laoyut Placement of the image and text.
*/
void contentPlacement(ContentLayout &layout) const
{
Rectanglei const contentRect = self.rule().recti().adjusted(margin.xy(), -margin.zw());
Rectanglei const contentRect = contentArea(); //self.rule().recti().adjusted(margin.xy(), -margin.zw());

Vector2f const imgSize = imageSize() * imageScale;

Expand Down Expand Up @@ -322,79 +338,63 @@ public Font::RichFormat::IStyle
// By default the image and the text are centered over each other.
layout.image.move((Vector2f(layout.text.size()) - layout.image.size()) / 2);

if(alignMode == AlignSeparately)
if(hasImage() && hasText())
{
// When aligning separately, simply align both the image and the text
// within the main content rectangle as specified.
if(hasImage())
// Determine the position of the image in relation to the text
// (keeping the image at its current position).
if(textAlign & AlignLeft)
{
applyAlignment(imageAlign, layout.image, contentRect);
layout.text.moveLeft(layout.image.left() - layout.text.width() - gap);
}
if(hasText())
if(textAlign & AlignRight)
{
applyAlignment(textAlign, layout.text, contentRect);
layout.text.moveLeft(layout.image.right() + gap);
}
}
else
{
if(hasImage() && hasText())
if(textAlign & AlignTop)
{
// Determine the position of the image in relation to the text
// (keeping the image at its current position).
if(textAlign & AlignLeft)
{
layout.text.moveLeft(layout.image.left() - layout.text.width() - gap);
}
if(textAlign & AlignRight)
{
layout.text.moveLeft(layout.image.right() + gap);
}
if(textAlign & AlignTop)
layout.text.moveTop(layout.image.top() - layout.text.height() - gap);
}
if(textAlign & AlignBottom)
{
layout.text.moveTop(layout.image.bottom() + gap);
}

// Align the image in relation to the text on the other axis.
if(textAlign & (AlignLeft | AlignRight))
{
if(imageAlign & AlignTop)
{
layout.text.moveTop(layout.image.top() - layout.text.height() - gap);
layout.image.moveTop(layout.text.top());
}
if(textAlign & AlignBottom)
if(imageAlign & AlignBottom)
{
layout.text.moveTop(layout.image.bottom() + gap);
layout.image.moveTop(layout.text.bottom() - layout.image.height());
}

// Align the image in relation to the text on the other axis.
if(textAlign & (AlignLeft | AlignRight))
}
if(textAlign & (AlignTop | AlignBottom))
{
if(imageAlign & AlignLeft)
{
if(imageAlign & AlignTop)
{
layout.image.moveTop(layout.text.top());
}
if(imageAlign & AlignBottom)
{
layout.image.moveTop(layout.text.bottom() - layout.image.height());
}
layout.image.moveLeft(layout.text.left());
}
if(textAlign & (AlignTop | AlignBottom))
if(imageAlign & AlignRight)
{
if(imageAlign & AlignLeft)
{
layout.image.moveLeft(layout.text.left());
}
if(imageAlign & AlignRight)
{
layout.image.moveLeft(layout.text.right() - layout.image.width());
}
layout.image.moveLeft(layout.text.right() - layout.image.width());
}
}
}

// Align the final combination within the content.
Rectanglef combined =
(alignMode == AlignByCombination? (layout.image | layout.text) :
alignMode == AlignOnlyByImage? layout.image :
layout.text);
// Align the final combination within the content.
Rectanglef combined =
(alignMode == AlignByCombination? (layout.image | layout.text) :
alignMode == AlignOnlyByImage? layout.image :
layout.text);

Vector2f delta = applyAlignment(align, combined.size(), contentRect);
delta -= combined.topLeft;
Vector2f delta = applyAlignment(align, combined.size(), contentRect);
delta -= combined.topLeft;

layout.image.move(delta);
layout.text.move(delta.toVector2i());
}
layout.image.move(delta);
layout.text.move(delta.toVector2i());
}

/**
Expand Down Expand Up @@ -479,6 +479,10 @@ public Font::RichFormat::IStyle
{
image->update();
}
if(!overlayImage.isNull())
{
overlayImage->update();
}

glText.setLineWrapWidth(availableTextWidth());
if(glText.update())
Expand Down Expand Up @@ -541,6 +545,12 @@ void LabelWidget::setImage(ProceduralImage *procImage)
d->image.reset(procImage);
}

void LabelWidget::setOverlayImage(ProceduralImage *overlayProcImage, ui::Alignment const &alignment)
{
d->overlayImage.reset(overlayProcImage);
d->overlayAlign = alignment;
}

String LabelWidget::text() const
{
return d->glText.text();
Expand Down Expand Up @@ -675,6 +685,13 @@ void LabelWidget::glMakeGeometry(DefaultVertexBuf::Builder &verts)
lineAlign, Vector4f(0, 0, 0, 1));*/
d->glText.makeVertices(verts, layout.text, AlignCenter, d->lineAlign, d->textGLColor);
}

if(!d->overlayImage.isNull())
{
Rectanglef rect = Rectanglef::fromSize(d->overlayImage->size());
applyAlignment(d->overlayAlign, rect, d->contentArea());
d->overlayImage->glMakeGeometry(verts, rect);
}
}

void LabelWidget::updateStyle()
Expand Down

0 comments on commit 7072dc9

Please sign in to comment.