1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-02-04 03:40:07 +00:00

Added typeface and kerning support to the Projucer GUI editor

This commit is contained in:
tpoole 2017-02-21 21:08:53 +00:00
parent 08707ec85c
commit b28555838d
3 changed files with 275 additions and 40 deletions

View file

@ -54,9 +54,14 @@ public:
e->setAttribute ("fontname", l->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont()).toString());
e->setAttribute ("fontsize", roundToInt (l->getFont().getHeight() * 100.0) / 100.0);
e->setAttribute ("kerning", roundToInt (l->getFont().getExtraKerningFactor() * 1000.0) / 1000.0);
e->setAttribute ("bold", l->getFont().isBold());
e->setAttribute ("italic", l->getFont().isItalic());
e->setAttribute ("justification", l->getJustificationType().getFlags());
if (l->getFont().getTypefaceStyle() != "Regular")
{
e->setAttribute ("typefaceStyle", l->getFont().getTypefaceStyle());
}
return e;
}
@ -74,6 +79,11 @@ public:
font.setHeight ((float) xml.getDoubleAttribute ("fontsize", 15.0));
font.setBold (xml.getBoolAttribute ("bold", false));
font.setItalic (xml.getBoolAttribute ("italic", false));
font.setExtraKerningFactor ((float) xml.getDoubleAttribute ("kerning", 0.0));
auto fontStyle = xml.getStringAttribute ("typefaceStyle");
if (! fontStyle.isEmpty())
font.setTypefaceStyle (fontStyle);
l->setFont (font);
l->getProperties().set ("typefaceName", xml.getStringAttribute ("fontname", FontPropertyComponent::getDefaultFont()));
@ -162,12 +172,12 @@ public:
ComponentTypeHandler::getEditableProperties (component, document, props);
Label* const l = dynamic_cast<Label*> (component);
props.add (new LabelTextProperty (l, document));
props.add (new LabelTextProperty (l, document));
props.add (new LabelJustificationProperty (l, document));
props.add (new FontNameProperty (l, document));
props.add (new FontSizeProperty (l, document));
props.add (new FontStyleProperty (l, document));
props.add (new FontNameProperty (l, document));
props.add (new FontStyleProperty (l, document));
props.add (new FontSizeProperty (l, document));
props.add (new FontKerningProperty (l, document));
addColourProperties (component, document, props);
@ -567,10 +577,7 @@ private:
{
document.addChangeListener (this);
choices.add ("normal");
choices.add ("bold");
choices.add ("italic");
choices.add ("bold + italic");
updateStylesList (label->getFont());
}
~FontStyleProperty()
@ -578,12 +585,44 @@ private:
document.removeChangeListener (this);
}
void updateStylesList (const Font& newFont)
{
if (getNumChildComponents() > 0)
{
if (auto cb = dynamic_cast<ComboBox*> (getChildComponent (0)))
cb->clear();
getChildComponent (0)->setVisible (false);
removeAllChildren();
}
choices.clear();
choices.add ("Regular");
choices.add ("Bold");
choices.add ("Italic");
choices.add ("Bold Italic");
choices.mergeArray (newFont.getAvailableStyles());
refresh();
}
void setIndex (int newIndex)
{
Font f (label->getFont());
f.setBold (newIndex == 1 || newIndex == 3);
f.setItalic (newIndex == 2 || newIndex == 3);
if (f.getAvailableStyles().contains (choices[newIndex]))
{
f.setBold (false);
f.setItalic (false);
f.setTypefaceStyle (choices[newIndex]);
}
else
{
f.setTypefaceStyle ("Regular");
f.setBold (newIndex == 1 || newIndex == 3);
f.setItalic (newIndex == 2 || newIndex == 3);
}
document.perform (new FontStyleChangeAction (label, *document.getComponentLayout(), f),
"Change Label font style");
@ -591,17 +630,28 @@ private:
int getIndex() const
{
if (label->getFont().isBold() && label->getFont().isItalic())
return 3;
else if (label->getFont().isBold())
return 1;
else if (label->getFont().isItalic())
return 2;
auto f = label->getFont();
return 0;
const auto typefaceIndex = choices.indexOf (f.getTypefaceStyle());
if (typefaceIndex == -1)
{
if (f.isBold() && f.isItalic())
return 3;
else if (f.isBold())
return 1;
else if (f.isItalic())
return 2;
return 0;
}
return typefaceIndex;
}
void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
void changeListenerCallback (ChangeBroadcaster*)
{
updateStylesList (label->getFont());
}
private:
Label* const label;
@ -636,4 +686,78 @@ private:
Font newState, oldState;
};
};
//==============================================================================
class FontKerningProperty : public SliderPropertyComponent,
public ChangeListener
{
public:
FontKerningProperty (Label* const label_, JucerDocument& doc)
: SliderPropertyComponent ("kerning", -0.5, 0.5, 0.001),
label (label_),
document (doc)
{
document.addChangeListener (this);
}
~FontKerningProperty()
{
document.removeChangeListener (this);
}
void setValue (double newValue)
{
document.getUndoManager().undoCurrentTransactionOnly();
document.perform (new FontKerningChangeAction (label, *document.getComponentLayout(), (float) newValue),
"Change Label font kerning");
}
double getValue() const
{
return label->getFont().getExtraKerningFactor();
}
void changeListenerCallback (ChangeBroadcaster*)
{
refresh();
}
private:
Label* const label;
JucerDocument& document;
class FontKerningChangeAction : public ComponentUndoableAction <Label>
{
public:
FontKerningChangeAction (Label* const comp, ComponentLayout& l, const float newState_)
: ComponentUndoableAction <Label> (comp, l),
newState (newState_)
{
oldState = comp->getFont().getExtraKerningFactor();
}
bool perform()
{
showCorrectTab();
Font f (getComponent()->getFont());
f.setExtraKerningFactor ((float) newState);
getComponent()->setFont (f);
changed();
return true;
}
bool undo()
{
showCorrectTab();
Font f (getComponent()->getFont());
f.setExtraKerningFactor ((float) oldState);
getComponent()->setFont (f);
changed();
return true;
}
float newState, oldState;
};
};
};

View file

@ -72,6 +72,7 @@ public:
props.add (new FontNameProperty (this));
props.add (new FontStyleProperty (this));
props.add (new FontSizeProperty (this));
props.add (new FontKerningProperty (this));
props.add (new TextJustificationProperty (this));
props.add (new TextToPathProperty (this));
}
@ -111,9 +112,14 @@ public:
e->setAttribute ("text", text);
e->setAttribute ("fontname", typefaceName);
e->setAttribute ("fontsize", roundToInt (font.getHeight() * 100.0) / 100.0);
e->setAttribute ("kerning", roundToInt (font.getExtraKerningFactor() * 1000.0) / 1000.0);
e->setAttribute ("bold", font.isBold());
e->setAttribute ("italic", font.isItalic());
e->setAttribute ("justification", justification.getFlags());
if (font.getTypefaceStyle() != "Regular")
{
e->setAttribute ("typefaceStyle", font.getTypefaceStyle());
}
return e;
}
@ -130,7 +136,11 @@ public:
font.setHeight ((float) xml.getDoubleAttribute ("fontsize", 15.0));
font.setBold (xml.getBoolAttribute ("bold", false));
font.setItalic (xml.getBoolAttribute ("italic", false));
font.setExtraKerningFactor ((float) xml.getDoubleAttribute ("kerning", 0.0));
justification = Justification (xml.getIntAttribute ("justification", Justification::centred));
auto fontStyle = xml.getStringAttribute ("typefaceStyle");
if (! fontStyle.isEmpty())
font.setTypefaceStyle (fontStyle);
return true;
}
@ -430,10 +440,7 @@ private:
{
element->getDocument()->addChangeListener (this);
choices.add ("normal");
choices.add ("bold");
choices.add ("italic");
choices.add ("bold + italic");
updateStylesList (element->getTypefaceName());
}
~FontStyleProperty()
@ -441,29 +448,72 @@ private:
element->getDocument()->removeChangeListener (this);
}
void updateStylesList (const String& name)
{
if (getNumChildComponents() > 0)
{
if (auto cb = dynamic_cast<ComboBox*> (getChildComponent (0)))
cb->clear();
getChildComponent (0)->setVisible (false);
removeAllChildren();
}
choices.clear();
choices.add ("Regular");
choices.add ("Bold");
choices.add ("Italic");
choices.add ("Bold Italic");
choices.mergeArray (Font::findAllTypefaceStyles (name));
refresh();
}
void setIndex (int newIndex)
{
Font f (element->getFont());
f.setBold (newIndex == 1 || newIndex == 3);
f.setItalic (newIndex == 2 || newIndex == 3);
if (f.getAvailableStyles().contains (choices[newIndex]))
{
f.setBold (false);
f.setItalic (false);
f.setTypefaceStyle (choices[newIndex]);
}
else
{
f.setTypefaceStyle ("Regular");
f.setBold (newIndex == 1 || newIndex == 3);
f.setItalic (newIndex == 2 || newIndex == 3);
}
element->setFont (f, true);
}
int getIndex() const
{
if (element->getFont().isBold() && element->getFont().isItalic())
return 3;
else if (element->getFont().isBold())
return 1;
else if (element->getFont().isItalic())
return 2;
auto f = element->getFont();
return 0;
const auto typefaceIndex = choices.indexOf (f.getTypefaceStyle());
if (typefaceIndex == -1)
{
if (f.isBold() && f.isItalic())
return 3;
else if (f.isBold())
return 1;
else if (f.isItalic())
return 2;
return 0;
}
return typefaceIndex;
}
void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
void changeListenerCallback (ChangeBroadcaster*)
{
updateStylesList (element->getTypefaceName());
}
private:
PaintElementText* const element;
@ -507,6 +557,47 @@ private:
PaintElementText* const element;
};
//==============================================================================
class FontKerningProperty : public SliderPropertyComponent,
public ChangeListener
{
public:
FontKerningProperty (PaintElementText* const e)
: SliderPropertyComponent ("kerning", -0.5, 0.5, 0.001),
element (e)
{
element->getDocument()->addChangeListener (this);
}
~FontKerningProperty()
{
element->getDocument()->removeChangeListener (this);
}
void setValue (double newValue)
{
element->getDocument()->getUndoManager().undoCurrentTransactionOnly();
Font f (element->getFont());
f.setExtraKerningFactor ((float) newValue);
element->setFont (f, true);
}
double getValue() const
{
return element->getFont().getExtraKerningFactor();
}
void changeListenerCallback (ChangeBroadcaster*)
{
refresh();
}
private:
PaintElementText* const element;
};
//==============================================================================
class TextJustificationProperty : public JustificationProperty,
public ChangeListener

View file

@ -84,7 +84,12 @@ public:
if (typefaceName == getDefaultSerif()) return Font (Font::getDefaultSerifFontName(), font.getHeight(), font.getStyleFlags());
if (typefaceName == getDefaultMono()) return Font (Font::getDefaultMonospacedFontName(), font.getHeight(), font.getStyleFlags());
return Font (typefaceName, font.getHeight(), font.getStyleFlags());
auto f = Font (typefaceName, font.getHeight(), font.getStyleFlags()).withExtraKerningFactor (font.getExtraKerningFactor());
if (f.getAvailableStyles().contains (font.getTypefaceStyle()))
{
f.setTypefaceStyle (font.getTypefaceStyle());
}
return f;
}
static String getTypefaceNameCode (const String& typefaceName)
@ -108,11 +113,26 @@ public:
static String getCompleteFontCode (const Font& font, const String& typefaceName)
{
return "Font ("
+ getTypefaceNameCode (typefaceName)
+ CodeHelpers::floatLiteral (font.getHeight(), 2)
+ ", "
+ getFontStyleCode (font)
+ ")";
String s;
s << "Font ("
<< getTypefaceNameCode (typefaceName)
<< CodeHelpers::floatLiteral (font.getHeight(), 2)
<< ", ";
if (font.getAvailableStyles().contains(font.getTypefaceStyle()))
s << "Font::plain).withTypefaceStyle ("
<< CodeHelpers::stringLiteral (font.getTypefaceStyle())
<< ")";
else
s << getFontStyleCode (font)
<< ")";
if (font.getExtraKerningFactor() != 0)
s << ".withExtraKerningFactor ("
<< CodeHelpers::floatLiteral (font.getExtraKerningFactor(), 3)
<< ")";
return s;
}
};