mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-12 05:36:59 -04:00
Fixed TextCtrl to work for keyword properties;
Added wrapping of <> around parameters to TextElement; Added colors for keyword parameters; Added menu & toolbar for keyword panel; Fixed bug in package, save/save-as was the wrong way around; Added third quality setting to RotatedDC: using SetUserScale, this gets you more precise positioning. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@250 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <data/field/text.hpp>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(TextElementP);
|
||||
DECLARE_POINTER_TYPE(FontTextElement);
|
||||
|
||||
// ----------------------------------------------------------------------------- : TextElements
|
||||
|
||||
@@ -56,14 +57,26 @@ double TextElements::scaleStep() const {
|
||||
return m;
|
||||
}
|
||||
|
||||
// Colors for <param> tags
|
||||
Color param_colors[] =
|
||||
{ Color(0,170,0)
|
||||
, Color(0,0,200)
|
||||
, Color(200,0,100)
|
||||
, Color(200,200,0)
|
||||
, Color(0,170,170)
|
||||
, Color(200,0,0)
|
||||
};
|
||||
|
||||
// Helper class for TextElements::fromString, to allow persistent formating state accross recusive calls
|
||||
struct TextElementsFromString {
|
||||
// What formatting is enabled?
|
||||
int bold, italic, symbol;
|
||||
int soft, kwpph, line;
|
||||
int soft, kwpph, param, line;
|
||||
int param_id;
|
||||
bool bracket;
|
||||
|
||||
TextElementsFromString()
|
||||
: bold(0), italic(0), symbol(0), soft(0), kwpph(0), line(0) {}
|
||||
: bold(0), italic(0), symbol(0), soft(0), kwpph(0), param(0), line(0), param_id(0), bracket(false) {}
|
||||
|
||||
// read TextElements from a string
|
||||
void fromString(TextElements& te, const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx) {
|
||||
@@ -84,6 +97,8 @@ struct TextElementsFromString {
|
||||
else if (is_substr(text, tag_start, _("</sep-soft"))) soft -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<atom-kwpph"))) kwpph += 1;
|
||||
else if (is_substr(text, tag_start, _("</atom-kwpph"))) kwpph -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<param"))) param += 1;
|
||||
else if (is_substr(text, tag_start, _("</param"))) param -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<line"))) line += 1;
|
||||
else if (is_substr(text, tag_start, _("</line"))) line -= 1;
|
||||
else if (is_substr(text, tag_start, _("<atom"))) {
|
||||
@@ -97,21 +112,40 @@ struct TextElementsFromString {
|
||||
// ignore other tags
|
||||
}
|
||||
} else {
|
||||
if (c == _('\1')) c = _('<'); // unescape
|
||||
// A character of normal text, add to the last text element (if possible)
|
||||
SimpleTextElement* e = nullptr;
|
||||
if (!te.elements.empty()) e = dynamic_cast<SimpleTextElement*>(te.elements.back().get());
|
||||
if (e && e->end == pos) {
|
||||
e->end = pos + 1; // just move the end, no need to make a new element
|
||||
if (e && e->end == (bracket ? pos + 1 : pos)) {
|
||||
e->end = bracket ? pos + 2 : pos + 1; // just move the end, no need to make a new element
|
||||
e->content += c;
|
||||
if (bracket) {
|
||||
// content is "<somethin>g" should be "<something>"
|
||||
swap(e->content[e->content.size() - 2], e->content[e->content.size() - 1]);
|
||||
}
|
||||
} else {
|
||||
// add a new element for this text
|
||||
if (symbol > 0 && style.symbol_font.valid()) {
|
||||
te.elements.push_back(new_shared5<SymbolTextElement>(text, pos, pos + 1, style.symbol_font, &ctx));
|
||||
e = new SymbolTextElement(text, pos, pos + 1, style.symbol_font, &ctx);
|
||||
bracket = false;
|
||||
} else {
|
||||
te.elements.push_back(new_shared6<FontTextElement> (text, pos, pos + 1,
|
||||
style.font.make(bold > 0, italic > 0, soft > 0 || kwpph > 0),
|
||||
soft > 0 ? DRAW_ACTIVE : DRAW_NORMAL,
|
||||
line > 0 ? BREAK_LINE : BREAK_HARD));
|
||||
FontP font = style.font.make(bold > 0, italic > 0, soft > 0 || kwpph > 0,
|
||||
param > 0 ? ¶m_colors[(param_id++) % (sizeof(param_colors)/sizeof(param_colors[0]))] : nullptr);
|
||||
bracket = kwpph > 0 || param > 0;
|
||||
e = new FontTextElement(
|
||||
text,
|
||||
bracket ? pos - 1 : pos,
|
||||
bracket ? pos + 2 : pos + 1,
|
||||
font,
|
||||
soft > 0 ? DRAW_ACTIVE : DRAW_NORMAL,
|
||||
line > 0 ? BREAK_LINE : BREAK_HARD);
|
||||
}
|
||||
if (bracket) {
|
||||
e->content = String(_("‹")) + c + _("›");
|
||||
} else {
|
||||
e->content = c;
|
||||
}
|
||||
te.elements.push_back(TextElementP(e));
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,10 @@ class TextElements : public vector<TextElementP> {
|
||||
/// A text element that just shows text
|
||||
class SimpleTextElement : public TextElement {
|
||||
public:
|
||||
SimpleTextElement(const String& text, size_t start ,size_t end) : TextElement(text, start, end) {}
|
||||
SimpleTextElement(const String& text, size_t start, size_t end)
|
||||
: TextElement(text, start, end), content(text.substr(start,end-start))
|
||||
{}
|
||||
String content; ///< Text to show
|
||||
};
|
||||
|
||||
/// A text element that uses a normal font
|
||||
|
||||
@@ -14,15 +14,18 @@
|
||||
void FontTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
if ((what & draw_as) != draw_as) return; // don't draw
|
||||
dc.SetFont(font->font, font->size * scale);
|
||||
if (end != start && text.substr(end-1, 1) == _("\n")) end -= 1; // don't draw the newline character at the end
|
||||
// draw shadow
|
||||
String text = content.substr(start - this->start, end - start);
|
||||
if (!text.empty() && text.GetChar(text.size() - 1) == _('\n')) {
|
||||
text = text.substr(0, text.size() - 1); // don't draw last \n
|
||||
}
|
||||
if (font->hasShadow()) {
|
||||
dc.SetTextForeground(font->shadow_color);
|
||||
dc.DrawText(text.substr(start, end - start), rect.position() + font->shadow_displacement);
|
||||
dc.DrawText(text, rect.position() + font->shadow_displacement);
|
||||
}
|
||||
// draw
|
||||
dc.SetTextForeground(font->color);
|
||||
dc.DrawText(text.substr(start, end - start), rect.position());
|
||||
dc.DrawText(text, rect.position());
|
||||
}
|
||||
|
||||
void FontTextElement::getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const {
|
||||
@@ -31,8 +34,8 @@ void FontTextElement::getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>&
|
||||
// find sizes & breaks
|
||||
double prev_width = 0;
|
||||
for (size_t i = start ; i < end ; ++i) {
|
||||
Char c = text.GetChar(i);
|
||||
RealSize s = dc.GetTextExtent(text.substr(start, i - start + 1));
|
||||
Char c = content.GetChar(i - this->start);
|
||||
RealSize s = dc.GetTextExtent(content.substr(start - this->start, i - start + 1));
|
||||
out.push_back(CharInfo(RealSize(s.width - prev_width, s.height),
|
||||
c == _('\n') ? break_style :
|
||||
c == _(' ') ? BREAK_SOFT : BREAK_NO
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
|
||||
void SymbolTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
if (font.font) {
|
||||
font.font->draw(dc, ctx, rect, font.size * scale, font.alignment, text.substr(start, end-start));
|
||||
font.font->draw(dc, ctx, rect, font.size * scale, font.alignment, content.substr(start - this->start, end-start));
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolTextElement::getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const {
|
||||
if (font.font) {
|
||||
font.font->getCharInfo(dc, ctx, font.size * scale, text.substr(start, end-start), out);
|
||||
font.font->getCharInfo(dc, ctx, font.size * scale, content.substr(start - this->start, end-start), out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -325,6 +325,36 @@ void TextViewer::prepareLines(RotatedDC& dc, const String& text, const TextStyle
|
||||
scale = next_scale;
|
||||
}
|
||||
|
||||
/*
|
||||
double scale_1 = 1.
|
||||
double fit_1 = fitLines(dc, text, style, scale_1);
|
||||
if (fit_1 <= 0 || scale_1 >= scale_2) {
|
||||
// ok
|
||||
} else {
|
||||
// find best text size, using the 'false position' root finding method
|
||||
double scale_2 = elements.minScale();
|
||||
double fit_2 = fitLines(dc, text, style, scale_2);
|
||||
if (fit_2 > 0) {
|
||||
// still doesn't fit at smallest size
|
||||
} else {
|
||||
// invariant: fit_1 > 0 && fit_2 <= 0
|
||||
while (abs(scale_2 - scale_1) > 0.01) {
|
||||
double scale_3 = scale_2 - fit_2 * (scale_2 - scale_1)/(fit_2 - fit_1);
|
||||
double fit_3 = fitLines(dc, text, style, scale_3);
|
||||
if (fit_3 > 0) {
|
||||
scale_2 = scale_3;
|
||||
fit_2 = fit_3;
|
||||
} else {
|
||||
scale_2 = scale_3;
|
||||
fit_2 = fit_3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns negative values if it fits, positive if it doesn't
|
||||
*/
|
||||
|
||||
// no text, find a dummy height for the single line we have
|
||||
if (lines.size() == 1 && lines[0].width() < 0.0001) {
|
||||
if (style.always_symbol && style.symbol_font.valid()) {
|
||||
|
||||
Reference in New Issue
Block a user