Skip to content

Commit 74d4ebe

Browse files
committed
Add LineSpacingDemo to show new GlyphArrangement option
1 parent 7242210 commit 74d4ebe

File tree

2 files changed

+218
-0
lines changed

2 files changed

+218
-0
lines changed

examples/DemoRunner/Source/Demos/DemoPIPs2.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "../../../GUI/GridDemo.h"
5151
#include "../../../GUI/ImagesDemo.h"
5252
#include "../../../GUI/KeyMappingsDemo.h"
53+
#include "../../../GUI/LineSpacingDemo.h"
5354
#include "../../../GUI/LookAndFeelDemo.h"
5455
#include "../../../GUI/MDIDemo.h"
5556
#include "../../../GUI/MenusDemo.h"
@@ -91,6 +92,7 @@ void registerDemos_Two() noexcept
9192
REGISTER_DEMO (GridDemo, GUI, false)
9293
REGISTER_DEMO (ImagesDemo, GUI, false)
9394
REGISTER_DEMO (KeyMappingsDemo, GUI, false)
95+
REGISTER_DEMO (LineSpacingDemo, GUI, false)
9496
REGISTER_DEMO (LookAndFeelDemo, GUI, false)
9597
REGISTER_DEMO (MDIDemo, GUI, false)
9698
REGISTER_DEMO (MenusDemo, GUI, false)

examples/GUI/LineSpacingDemo.h

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
==============================================================================
3+
4+
This file is part of the JUCE framework examples.
5+
Copyright (c) Raw Material Software Limited
6+
7+
The code included in this file is provided under the terms of the ISC license
8+
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
9+
to use, copy, modify, and/or distribute this software for any purpose with or
10+
without fee is hereby granted provided that the above copyright notice and
11+
this permission notice appear in all copies.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19+
PERFORMANCE OF THIS SOFTWARE.
20+
21+
==============================================================================
22+
*/
23+
24+
/*******************************************************************************
25+
The block below describes the properties of this PIP. A PIP is a short snippet
26+
of code that can be read by the Projucer and used to generate a JUCE project.
27+
28+
BEGIN_JUCE_PIP_METADATA
29+
30+
name: LineSpacingDemo
31+
version: 1.0.0
32+
vendor: JUCE
33+
website: http://juce.com
34+
description: Demonstrates the line spacing options of GlyphArrangement.
35+
36+
dependencies: juce_core, juce_events, juce_data_structures, juce_graphics,
37+
juce_gui_basics
38+
exporters: xcode_mac, vs2022, linux_make, androidstudio, xcode_iphone
39+
40+
moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1
41+
42+
type: Component
43+
mainClass: LineSpacingDemo
44+
45+
useLocalCopy: 1
46+
47+
END_JUCE_PIP_METADATA
48+
49+
*******************************************************************************/
50+
51+
#pragma once
52+
53+
//==============================================================================
54+
struct LineSpacingDemo final : public Component
55+
{
56+
LineSpacingDemo()
57+
{
58+
lineSpacingSlider.setRange (0.0, 40.0, 0.1);
59+
lineHeightMultipleSlider.setRange (1.0, 3.0, 0.1);
60+
61+
Slider* sliders[] { &lineSpacingSlider, &lineHeightMultipleSlider };
62+
63+
for (auto* s : sliders)
64+
s->onValueChange = [this] { update(); };
65+
66+
lineSpacingLabel.attachToComponent (&lineSpacingSlider, false);
67+
lineHeightMultipleLabel.attachToComponent (&lineHeightMultipleSlider, false);
68+
69+
demoDescription.setJustificationType (Justification::centredLeft);
70+
71+
Component* components[] { &lineSpacingLabel,
72+
&lineHeightMultipleLabel,
73+
&lineSpacingSlider,
74+
&lineHeightMultipleSlider,
75+
&demoDescription };
76+
77+
for (auto* c : components)
78+
addAndMakeVisible (c);
79+
80+
setSize (700, 500);
81+
}
82+
83+
String justified = "addJustifiedText() places the baseline at the y argument. It will wrap lines "
84+
"to enforce the maximum width, but it cannot be "
85+
"vertically constrained. The specified Font options will always be respected. "
86+
"Alignment and line spacing can be adjusted.";
87+
88+
String fitted = "addFittedText() places the top of the first line at the y argument. It can be "
89+
"vertically constrained. It uses the specified Font as a default, but it will "
90+
"reduce the font size and squash the text if necessary to fit it in the available "
91+
"space.";
92+
93+
static constexpr int demoAreaPadding = 10;
94+
95+
Rectangle<int> getDemoBounds() const
96+
{
97+
return getLocalBounds().withTrimmedTop (220).reduced (demoAreaPadding).withTrimmedBottom (40);
98+
}
99+
100+
Rectangle<int> getJustifiedBounds() const
101+
{
102+
auto bounds = getDemoBounds();
103+
auto half = bounds.removeFromLeft (bounds.getWidth() / 2);
104+
half.removeFromRight (25);
105+
return half;
106+
}
107+
108+
Rectangle<int> getFittedBounds() const
109+
{
110+
auto bounds = getDemoBounds();
111+
auto half = bounds.removeFromRight (bounds.getWidth() / 2);
112+
half.removeFromLeft (25);
113+
return half;
114+
}
115+
116+
void paintGuideLines (Graphics& g)
117+
{
118+
const auto textColour = getLookAndFeel().findColour (Label::textColourId);
119+
const auto lineColour = textColour.withSaturation (0.4f).withRotatedHue (0.1f);
120+
121+
g.setColour (lineColour);
122+
const auto demoBounds = getDemoBounds().toFloat();
123+
g.drawLine (demoBounds.getCentreX() - 90.0f,
124+
demoBounds.getY(),
125+
demoBounds.getCentreX() + 90.0f,
126+
demoBounds.getY(),
127+
1.5f);
128+
129+
const auto jb = getJustifiedBounds().toFloat();
130+
const auto jbMin = jb.getY() - font.getAscent();
131+
const auto jbMax = (float) jb.getBottom();
132+
g.drawLine (jb.getX(), jbMin, jb.getX(), jbMax, 1.5f);
133+
g.drawLine (jb.getRight(), jbMin, jb.getRight(), jbMax, 1.5f);
134+
135+
const auto fb = getFittedBounds().toFloat();
136+
g.drawLine (fb.getX(), fb.getY(), fb.getX(), fb.getBottom(), 1.5f);
137+
g.drawLine (fb.getRight(), fb.getY(), fb.getRight(), fb.getBottom(), 1.5f);
138+
g.drawLine (fb.getX(), fb.getBottom(), fb.getX() + 10.0f, fb.getBottom(), 1.5f);
139+
g.drawLine (fb.getRight(), fb.getBottom(), fb.getRight() - 10.0f, fb.getBottom(), 1.5f);
140+
141+
g.setColour (textColour);
142+
g.drawText ("y",
143+
Rectangle { 40.0f, 20.0f }.withCentre ({ demoBounds.getCentreX(), demoBounds.getY() - 6.0f }),
144+
Justification::centredTop);
145+
}
146+
147+
void paint (Graphics& g) override
148+
{
149+
paintGuideLines (g);
150+
paintGlyphArrangement (g);
151+
}
152+
153+
void paintGlyphArrangement (Graphics& g)
154+
{
155+
g.setColour (getLookAndFeel().findColour (Label::textColourId));
156+
ga.draw (g);
157+
}
158+
159+
void resized() override
160+
{
161+
auto bounds = getLocalBounds().reduced (demoAreaPadding);
162+
163+
auto sliderBounds = bounds.removeFromRight (260);
164+
sliderBounds.removeFromTop (30);
165+
lineSpacingSlider.setBounds (sliderBounds.removeFromTop (35));
166+
sliderBounds.removeFromTop (25);
167+
lineHeightMultipleSlider.setBounds (sliderBounds.removeFromTop (45));
168+
169+
bounds.removeFromRight (10);
170+
demoDescription.setBounds (bounds.removeFromTop (lineHeightMultipleSlider.getBottom()));
171+
update();
172+
}
173+
174+
void update()
175+
{
176+
ga.clear();
177+
178+
const auto options = GlyphArrangement::Options{}.withLineSpacing ((float) lineSpacingSlider.getValue())
179+
.withLineHeightMultiple ((float) lineHeightMultipleSlider.getValue());
180+
181+
const auto leftBounds = getJustifiedBounds().toFloat();
182+
ga.addJustifiedText (font,
183+
justified,
184+
leftBounds.getX(),
185+
leftBounds.getY(),
186+
leftBounds.getWidth(),
187+
Justification::centredTop,
188+
options.getLineSpacing());
189+
190+
const auto rightBounds = getFittedBounds().toFloat();
191+
ga.addFittedText (font,
192+
fitted,
193+
rightBounds.getX(),
194+
rightBounds.getY(),
195+
rightBounds.getWidth(),
196+
rightBounds.getHeight(),
197+
Justification::centredTop,
198+
20,
199+
0.0f,
200+
options);
201+
202+
repaint();
203+
}
204+
205+
Font font = FontOptions{}.withPointHeight (16.0f);
206+
GlyphArrangement ga;
207+
Slider lineSpacingSlider { Slider::LinearHorizontal, Slider::TextBoxLeft };
208+
Slider lineHeightMultipleSlider { Slider::LinearHorizontal, Slider::TextBoxLeft };
209+
Label lineSpacingLabel { {}, "Line spacing:" };
210+
Label lineHeightMultipleLabel { {}, "Line height multiple (fitted text only):" };
211+
Label demoDescription { {}, "This demo showcases the GlyphArrangement class. Once constructed it "
212+
"can be redrawn efficiently. Two important functions are addJustifiedText "
213+
"and addFittedText." };
214+
215+
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LineSpacingDemo)
216+
};

0 commit comments

Comments
 (0)