Skip to content

Commit

Permalink
Fixed|LabelWidget|Client|UI: Image/text positioning, gap rule
Browse files Browse the repository at this point in the history
LabelWidget now uses a style rule to define the gap between an image
and a text in the label. Also, image fitting was improved so that
it doesn't mess up text positioning: image is fitted completely
before the text is positioned beside it.
  • Loading branch information
skyjake committed Aug 2, 2013
1 parent 60baf2b commit 8bcdfc2
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 55 deletions.
8 changes: 8 additions & 0 deletions doomsday/client/data/defaultstyle.pack/rules.dei
Expand Up @@ -9,6 +9,14 @@ rule halfunit { constant $= UNIT / 2 }
rule gap { constant $= UNIT * 3 }
rule glow { constant $= UNIT * 8 }

group label {
rule gap { constant $= gap.constant / 2 }
}

group progress {
rule textgap { constant $= gap.constant }
}

group console {
rule width { constant = 500 }
}
Expand Down
19 changes: 17 additions & 2 deletions doomsday/client/include/ui/widgets/labelwidget.h
Expand Up @@ -70,13 +70,28 @@ class LabelWidget : public GuiWidget

de::String text() const;

/**
* Sets the gap between the text and image. Defaults to "label.gap".
*
* @param styleRuleId Id of a rule in the style.
*/
void setTextGap(de::DotPath const &styleRuleId);

enum AlignmentMode {
AlignByCombination,
AlignOnlyByImage,
AlignOnlyByText
};

/**
* Sets the alignment of the entire contents of the widget inside its
* rectangle.
*
* @param align Alignment for all content.
* @param align Alignment for all content.
* @param alignMode Mode of alignment (by combo/text/image).
*/
void setAlignment(ui::Alignment const &align);
void setAlignment(ui::Alignment const &align,
AlignmentMode alignMode = AlignByCombination);

void setTextAlignment(ui::Alignment const &textAlign);

Expand Down
123 changes: 70 additions & 53 deletions doomsday/client/src/ui/widgets/labelwidget.cpp
Expand Up @@ -36,6 +36,7 @@ public Font::RichFormat::IStyle

SizePolicy horizPolicy;
SizePolicy vertPolicy;
AlignmentMode alignMode;
Alignment align;
Alignment textAlign;
Alignment lineAlign;
Expand All @@ -49,6 +50,7 @@ public Font::RichFormat::IStyle

// Style.
int margin;
DotPath gapId;
int gap;
ColorBank::Color highlightColor;
ColorBank::Color dimmedColor;
Expand All @@ -70,13 +72,15 @@ public Font::RichFormat::IStyle
Instance(Public *i)
: Base(i),
horizPolicy(Fixed), vertPolicy(Fixed),
alignMode(AlignByCombination),
align(AlignCenter),
textAlign(AlignCenter),
lineAlign(AlignCenter),
imageAlign(AlignCenter),
imageFit(OriginalAspectRatio | FitToSize),
imageScale(1),
imageColor(1, 1, 1, 1),
gapId("label.gap"),
wrapWidth(0),
needImageUpdate(false),
imageTex(Id::None),
Expand All @@ -101,7 +105,7 @@ public Font::RichFormat::IStyle
Style const &st = self.style();

margin = self.margin().valuei();
gap = margin / 2;
gap = st.rules().rule(gapId).valuei();

// Colors.
highlightColor = st.colors().color("label.highlight");
Expand Down Expand Up @@ -194,6 +198,7 @@ public Font::RichFormat::IStyle
void contentPlacement(ContentLayout &layout) const
{
Rectanglei const contentRect = self.rule().recti().shrunk(margin);

Vector2f const imageSize = image.size() * imageScale;

// Determine the sizes of the elements first.
Expand All @@ -204,27 +209,74 @@ public Font::RichFormat::IStyle
{
if(textAlign & (AlignLeft | AlignRight))
{
layout.image.setWidth(int(contentRect.width()) - int(layout.text.width()) - gap);
layout.image.setWidth(imageScale * (int(contentRect.width()) -
int(layout.text.width()) - gap));
}
else
{
layout.image.setWidth(contentRect.width());
layout.image.setWidth(imageScale * contentRect.width());
layout.text.setWidth(contentRect.width());
}
}
if(vertPolicy == Filled)
{
if(textAlign & (AlignTop | AlignBottom))
{
layout.image.setHeight(int(contentRect.height()) - int(layout.text.height()) - gap);
layout.image.setHeight(imageScale * (int(contentRect.height()) -
int(layout.text.height()) - gap));
}
else
{
layout.image.setHeight(contentRect.height());
layout.image.setHeight(imageScale * contentRect.height());
layout.text.setHeight(contentRect.height());
}
}

if(hasImage())
{
// Figure out how much room is left for the image.
Rectanglef const rect = layout.image;

// Fit the image.
if(!imageFit.testFlag(FitToWidth))
{
layout.image.setWidth(image.width());
}
if(!imageFit.testFlag(FitToHeight))
{
layout.image.setHeight(image.height());
}

// Should the original aspect ratio be preserved?
if(imageFit & OriginalAspectRatio)
{
if(imageFit & FitToWidth)
{
layout.image.setHeight(image.height() * layout.image.width() / image.width());
}
if(imageFit & FitToHeight)
{
layout.image.setWidth(image.width() * layout.image.height() / image.height());

if(imageFit.testFlag(FitToWidth))
{
float scale = 1;
if(layout.image.width() > rect.width())
{
scale = float(rect.width()) / float(layout.image.width());
}
else if(layout.image.height() > rect.height())
{
scale = float(rect.height()) / float(layout.image.height());
}
layout.image.setSize(Vector2f(layout.image.size()) * scale);
}
}
}

//applyAlignment(imageAlign, layout.image, rect);
}

// By default the image and the text are centered over each other.
layout.image.move((Vector2f(layout.text.size()) - layout.image.size()) / 2);

Expand Down Expand Up @@ -271,59 +323,17 @@ public Font::RichFormat::IStyle
}
}

// Align the combination within the content.
Rectanglef combined = 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;

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

if(hasImage())
{
// Figure out how much room is left for the image.
Rectanglef const rect = layout.image;

// Fit the image.
if(!imageFit.testFlag(FitToWidth))
{
layout.image.setWidth(image.width());
}
if(!imageFit.testFlag(FitToHeight))
{
layout.image.setHeight(image.height());
}

// Should the original aspect ratio be preserved?
if(imageFit & OriginalAspectRatio)
{
if(imageFit & FitToWidth)
{
layout.image.setHeight(image.height() * layout.image.width() / image.width());
}
if(imageFit & FitToHeight)
{
layout.image.setWidth(image.width() * layout.image.height() / image.height());

if(imageFit.testFlag(FitToWidth))
{
float scale = 1;
if(layout.image.width() > rect.width())
{
scale = float(rect.width()) / float(layout.image.width());
}
else if(layout.image.height() > rect.height())
{
scale = float(rect.height()) / float(layout.image.height());
}
layout.image.setSize(Vector2f(layout.image.size()) * scale);
}
}
}

applyAlignment(imageAlign, layout.image, rect);
}
}

Vector2ui textSize() const
Expand Down Expand Up @@ -432,9 +442,16 @@ String LabelWidget::text() const
return d->styledText;
}

void LabelWidget::setAlignment(Alignment const &align)
void LabelWidget::setTextGap(const DotPath &styleRuleId)
{
d->gapId = styleRuleId;
d->updateStyle();
}

void LabelWidget::setAlignment(Alignment const &align, AlignmentMode mode)
{
d->align = align;
d->alignMode = mode;
}

void LabelWidget::setTextAlignment(Alignment const &textAlign)
Expand Down

0 comments on commit 8bcdfc2

Please sign in to comment.