mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 05:07:00 -04:00
add font picker, color picker and bullet point ui tools
This commit is contained in:
@@ -180,6 +180,9 @@ void queue_message(MessageType type, String const& msg) {
|
||||
// Only show errors in the main thread
|
||||
message_queue.push_front(make_pair(type,msg));
|
||||
}
|
||||
void qm(String const& msg) {
|
||||
queue_message(MESSAGE_ERROR, msg);
|
||||
}
|
||||
|
||||
void handle_error(const Error& e) {
|
||||
queue_message(e.is_fatal() ? MESSAGE_FATAL_ERROR : MESSAGE_ERROR, e.what());
|
||||
|
||||
@@ -154,6 +154,7 @@ enum MessageType
|
||||
/** If the message is a MESSAGE_FATAL_ERROR, and show_message_box_for_fatal_errors==true, then a popup is shown
|
||||
*/
|
||||
void queue_message(MessageType type, String const& msg);
|
||||
void qm(String const& msg);
|
||||
/// Handle an error by queuing a message
|
||||
void handle_error(const Error& e);
|
||||
/// Handle an error by showing a message box
|
||||
|
||||
+78
-24
@@ -25,8 +25,8 @@ wxUniChar tag_char(wxUniChar c) {
|
||||
|
||||
// Is a character the "end" of the tag name?
|
||||
// don't mistake <tag> as <t>, only <t>, <t-stuff> and <t:stuff> are considered <t>
|
||||
bool is_tag_end_char(Char c) {
|
||||
return c == '>' || c == '-' || c == ':' || c == ' ';
|
||||
bool is_tag_end_char(Char c, bool strict) {
|
||||
return strict ? c == '>' : c == '>' || c == '-' || c == ':' || c == ' ';
|
||||
}
|
||||
|
||||
|
||||
@@ -162,11 +162,11 @@ String fix_old_tags(const String& str) {
|
||||
return skip_all_tags(it, end, after_open, after_close);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_tag(String::const_iterator it, String::const_iterator end, const char* tag) {
|
||||
[[nodiscard]] bool is_tag(String::const_iterator it, String::const_iterator end, const char* tag, bool strict) {
|
||||
for (; *tag; ++it, ++tag) {
|
||||
if (it == end || *it != *tag) return false;
|
||||
}
|
||||
if (it == end || !is_tag_end_char(*it)) return false;
|
||||
if (it == end || !is_tag_end_char(*it, strict)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -267,11 +267,25 @@ String::const_iterator find_close_tag(String::const_iterator tag, String::const_
|
||||
return String::npos;
|
||||
}
|
||||
|
||||
bool is_tag(const String& str, size_t pos, const String& tag) {
|
||||
return is_substr(str, pos, tag) && pos+tag.size() < str.size() && is_tag_end_char(str[pos+tag.size()]);
|
||||
bool is_tag(const String& str, size_t pos, const String& tag, bool strict) {
|
||||
return is_substr(str, pos, tag) && pos+tag.size() < str.size() && is_tag_end_char(str[pos+tag.size()], strict);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t in_tag(const String& str, const String& tag, size_t start, size_t end) {
|
||||
bool is_formatting_tag(const String& str, size_t pos) {
|
||||
if (str.size() < pos + 2) return false;
|
||||
if (str.GetChar(pos) != '<') return false;
|
||||
pos++;
|
||||
return is_substr(str, pos, _("b")) || is_substr(str, pos, _("/b")) ||
|
||||
is_substr(str, pos, _("i")) || is_substr(str, pos, _("/i")) ||
|
||||
is_substr(str, pos, _("sym")) || is_substr(str, pos, _("/sym")) ||
|
||||
is_substr(str, pos, _("u")) || is_substr(str, pos, _("/u")) ||
|
||||
is_substr(str, pos, _("strike")) || is_substr(str, pos, _("/strike")) ||
|
||||
is_substr(str, pos, _("font")) || is_substr(str, pos, _("/font")) ||
|
||||
is_substr(str, pos, _("size")) || is_substr(str, pos, _("/size")) ||
|
||||
is_substr(str, pos, _("color")) || is_substr(str, pos, _("/color"));
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t in_tag(const String& str, const String& tag, size_t start, size_t end, bool strict) {
|
||||
size_t last_start = String::npos;
|
||||
size_t size = str.size();
|
||||
int taglevel = 0;
|
||||
@@ -279,10 +293,10 @@ bool is_tag(const String& str, size_t pos, const String& tag) {
|
||||
for (size_t pos = 0 ; pos < end ; ) {
|
||||
Char c = str.GetChar(pos);
|
||||
if (c == _('<')) {
|
||||
if (is_substr(str, pos + 1, static_cast<const Char*>(tag.c_str())+1) && pos+tag.size() < str.size() && is_tag_end_char(str[pos+tag.size()])) {
|
||||
if (is_substr(str, pos + 1, static_cast<const Char*>(tag.c_str())+1) && pos+tag.size() < str.size() && is_tag_end_char(str[pos+tag.size()], strict)) {
|
||||
if (pos < start) last_start = pos;
|
||||
++taglevel;
|
||||
} else if (pos + 2 < size && str.GetChar(pos+1) == _('/') && is_substr(str, pos + 2, static_cast<const Char*>(tag.c_str())+1) && pos+1+tag.size() < str.size() && is_tag_end_char(str[pos+1+tag.size()])) {
|
||||
} else if (pos + 2 < size && str.GetChar(pos+1) == _('/') && is_substr(str, pos + 2, static_cast<const Char*>(tag.c_str())+1) && pos+1+tag.size() < str.size() && is_tag_end_char(str[pos+1+tag.size()], strict)) {
|
||||
--taglevel; // close tag
|
||||
}
|
||||
pos = skip_tag(str,pos);
|
||||
@@ -296,8 +310,8 @@ bool is_tag(const String& str, size_t pos, const String& tag) {
|
||||
}
|
||||
return taglevel < 1 ? String::npos : last_start;
|
||||
}
|
||||
bool is_in_tag(const String& str, const String& tag, size_t start, size_t end) {
|
||||
return in_tag(str,tag,start,end) != String::npos;
|
||||
bool is_in_tag(const String& str, const String& tag, size_t start, size_t end, bool strict) {
|
||||
return in_tag(str,tag,start,end,strict) != String::npos;
|
||||
}
|
||||
|
||||
|
||||
@@ -325,6 +339,17 @@ String anti_tag(const String& tag) {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Cursor position
|
||||
|
||||
size_t to_untagged_pos(const String& str, size_t pos) {
|
||||
return untag(str.substr(0, pos)).size();
|
||||
}
|
||||
|
||||
size_t to_tagged_pos(const String& str, size_t pos, bool after_open, bool after_close) {
|
||||
String::const_iterator it = str.begin();
|
||||
const String::const_iterator end = str.end();
|
||||
it = advance_untagged(it, end, pos, after_open, after_close);
|
||||
return std::distance(str.begin(), it);
|
||||
}
|
||||
|
||||
size_t index_to_cursor(const String& str, size_t index, Movement dir) {
|
||||
size_t cursor = 0;
|
||||
index = min(index, str.size());
|
||||
@@ -335,7 +360,11 @@ size_t index_to_cursor(const String& str, size_t index, Movement dir) {
|
||||
bool has_width = true;
|
||||
if (c == _('<')) {
|
||||
// a tag
|
||||
if (is_substr(str, i, _("<atom")) || is_substr(str, i, _("<sep"))) {
|
||||
if (is_substr(str, i, _("<atom")) ||
|
||||
is_substr(str, i, _("<sep")) ||
|
||||
is_substr(str, i, _("<bullet")) ||
|
||||
is_substr(str, i, _("<soft-line")) ||
|
||||
is_substr(str, i, _("<line"))) {
|
||||
// skip tag contents, tag counts as a single 'character'
|
||||
size_t before = i;
|
||||
size_t close = match_close_tag(str, i);
|
||||
@@ -426,7 +455,11 @@ void cursor_to_index_range(const String& str, size_t cursor, size_t& start, size
|
||||
bool has_width = true;
|
||||
if (c == _('<')) {
|
||||
// a tag
|
||||
if (is_substr(str, i, _("<atom")) || is_substr(str, i, _("<sep"))) {
|
||||
if (is_substr(str, i, _("<atom")) ||
|
||||
is_substr(str, i, _("<sep")) ||
|
||||
is_substr(str, i, _("<bullet")) ||
|
||||
is_substr(str, i, _("<soft-line")) ||
|
||||
is_substr(str, i, _("<line"))) {
|
||||
// never move the end over an atom/sep
|
||||
if (cur >= cursor) { ++i; break; }
|
||||
// skip tag contents, tag counts as a single 'character'
|
||||
@@ -504,6 +537,15 @@ String untag_for_cursor(const String& str) {
|
||||
} else if (is_substr(str, i, _("<sep"))) {
|
||||
i = match_close_tag_end(str, i);
|
||||
ret += UNTAG_SEP;
|
||||
} else if (is_substr(str, i, _("<bullet"))) {
|
||||
i = match_close_tag_end(str, i);
|
||||
ret += UNTAG_BULLET;
|
||||
} else if (is_substr(str, i, _("<soft-line"))) {
|
||||
i = match_close_tag_end(str, i);
|
||||
ret += UNTAG_ATOM;
|
||||
} else if (is_substr(str, i, _("<line"))) {
|
||||
i = match_close_tag_end(str, i);
|
||||
ret += UNTAG_ATOM;
|
||||
} else if (i == 0 && is_substr(str, i, _("<prefix"))) {
|
||||
// prefix at start of string, skip contents, index never before
|
||||
i = match_close_tag_end(str,i);
|
||||
@@ -555,7 +597,14 @@ size_t index_to_untagged(const String& str, size_t index) {
|
||||
return p;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Global operations
|
||||
// ----------------------------------------------------------------------------- : Global operations
|
||||
|
||||
String wrap_tag(const String& str, const String& tag) {
|
||||
return tag + str + close_tag(tag);
|
||||
}
|
||||
String anti_wrap_tag(const String& str, const String& tag) {
|
||||
return close_tag(tag) + str + tag;
|
||||
}
|
||||
|
||||
String remove_tag(const String& str, const String& tag) {
|
||||
if (tag.size() < 1) return str;
|
||||
@@ -641,14 +690,18 @@ String simplify_tagged(const String& str) {
|
||||
|
||||
// Add a tag to a stack of tags, try to cancel it out
|
||||
// If </tag> is in stack remove it and returns true
|
||||
// otherwise appends <tag> and returns fales
|
||||
// otherwise appends <tag> and returns false
|
||||
// (where </tag> is the negation of tag)
|
||||
bool add_or_cancel_tag(const String& tag, String& stack, bool all = false) {
|
||||
if (all || starts_with(tag, _("/")) ||
|
||||
starts_with(tag, _("b")) ||
|
||||
starts_with(tag, _("i")) ||
|
||||
starts_with(tag, _("sym")) ||
|
||||
starts_with(tag, _("u")) ||
|
||||
starts_with(tag, _("sym"))) {
|
||||
starts_with(tag, _("strike")) ||
|
||||
starts_with(tag, _("color")) ||
|
||||
starts_with(tag, _("font")) ||
|
||||
starts_with(tag, _("size"))) {
|
||||
// cancel out all close tags, but not all open tags,
|
||||
// so <xx></xx> is always removed
|
||||
// but </xx><xx> is not
|
||||
@@ -669,9 +722,9 @@ bool add_or_cancel_tag(const String& tag, String& stack, bool all = false) {
|
||||
}
|
||||
|
||||
String simplify_tagged_merge(const String& str, bool all) {
|
||||
String ret; ret.reserve(str.size());
|
||||
String waiting_tags; // tags that are waiting to be written to the output
|
||||
size_t size = str.size();
|
||||
String ret; ret.reserve(size);
|
||||
String waiting_tags; // tags that are waiting to be written to the output
|
||||
for (size_t i = 0 ; i < size ; ++i) {
|
||||
Char c = str.GetChar(i);
|
||||
if (c == _('<')) {
|
||||
@@ -688,17 +741,18 @@ String simplify_tagged_merge(const String& str, bool all) {
|
||||
}
|
||||
|
||||
String simplify_tagged_overlap(const String& str) {
|
||||
String ret; ret.reserve(str.size());
|
||||
String open_tags; // tags we are in
|
||||
size_t size = str.size();
|
||||
String ret; ret.reserve(size);
|
||||
String open_tags; // tags we are in
|
||||
for (size_t i = 0 ; i < size ; ++i) {
|
||||
Char c = str.GetChar(i);
|
||||
if (c == _('<')) {
|
||||
String tag = tag_at(str, i);
|
||||
if (starts_with(tag, _("b")) || starts_with(tag, _("/b")) ||
|
||||
starts_with(tag, _("i")) || starts_with(tag, _("/i")) ||
|
||||
starts_with(tag, _("u")) || starts_with(tag, _("/u")) ||
|
||||
starts_with(tag, _("sym")) || starts_with(tag, _("/sym"))) {
|
||||
if (starts_with(tag, _("b")) || starts_with(tag, _("/b")) ||
|
||||
starts_with(tag, _("i")) || starts_with(tag, _("/i")) ||
|
||||
starts_with(tag, _("sym")) || starts_with(tag, _("/sym")) ||
|
||||
starts_with(tag, _("u")) || starts_with(tag, _("/u")) ||
|
||||
starts_with(tag, _("strike")) || starts_with(tag, _("/strike"))) {
|
||||
// optimize this tag
|
||||
if (open_tags.find(_("<") + tag + _(">")) == String::npos) {
|
||||
// we are not already inside this tag
|
||||
|
||||
@@ -74,7 +74,11 @@ String fix_old_tags(const String&);
|
||||
|
||||
/// Does a string contain a tag at the given location?
|
||||
/** Only matches if the tag ends one of ">-: " */
|
||||
[[nodiscard]] bool is_tag(const String& str, size_t pos, const String& tag);
|
||||
[[nodiscard]] bool is_tag(const String& str, size_t pos, const String& tag, bool strict = false);
|
||||
|
||||
/// Does a string contain a tag at the given location?
|
||||
/** Matches <b <i <u <strike <font <size <color <sym or their anti tags */
|
||||
[[nodiscard]] bool is_formatting_tag(const String& str, size_t pos);
|
||||
|
||||
/// Is the given range entirely contained in a given tagged block?
|
||||
/** If so: return the start position of that tag, otherwise returns String::npos
|
||||
@@ -83,9 +87,9 @@ String fix_old_tags(const String&);
|
||||
* <tag><tag></tag>x</tag>
|
||||
* the x is in_tag
|
||||
*/
|
||||
[[nodiscard]] size_t in_tag(const String& str, const String& tag, size_t start, size_t end);
|
||||
[[nodiscard]] size_t in_tag(const String& str, const String& tag, size_t start, size_t end, bool strict = false);
|
||||
/// Boolean returning version of the above
|
||||
bool is_in_tag(const String& str, const String& tag, size_t start, size_t end);
|
||||
bool is_in_tag(const String& str, const String& tag, size_t start, size_t end, bool strict = false);
|
||||
|
||||
/// Return the tag at the given position (without the <>)
|
||||
String tag_at(const String& str, size_t pos);
|
||||
@@ -120,16 +124,25 @@ String anti_tag(const String& tag);
|
||||
[[nodiscard]] String::const_iterator find_close_tag(String::const_iterator it, String::const_iterator end);
|
||||
|
||||
/// Does a string contain a tag at the given location?
|
||||
/** Only matches if the tag in the text ends one of ">-: "
|
||||
/** Only matches if the tag in the text ends with one of ">-: "
|
||||
* If strict is set to true then it must end with exactly ">"
|
||||
* tag should be "<tag" or "</tag"
|
||||
*/
|
||||
[[nodiscard]] bool is_tag(String::const_iterator it, String::const_iterator end, const char* tag);
|
||||
[[nodiscard]] bool is_tag(String::const_iterator it, String::const_iterator end, const char* tag, bool strict = false);
|
||||
|
||||
// Length of a string when not counting tags
|
||||
// For example: untagged_length("<b>abc</b>",_) = 3
|
||||
[[nodiscard]] size_t untagged_length(String::const_iterator it, String::const_iterator end);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Cursor position
|
||||
|
||||
/// Take a tagged string and a position inside it,
|
||||
/// return the position if the string was untagged.
|
||||
size_t to_untagged_pos(const String& str, size_t pos);
|
||||
|
||||
/// Take a tagged string and a position inside the untagged version,
|
||||
/// return the position in the tagged version.
|
||||
size_t to_tagged_pos(const String& str, size_t pos, bool after_open=false, bool after_close=false);
|
||||
|
||||
/// Directions of cursor movement
|
||||
enum Movement
|
||||
@@ -158,6 +171,7 @@ size_t cursor_to_index(const String& str, size_t cursor, Movement dir = MOVE_MID
|
||||
const Char UNTAG_ATOM = _('\2');
|
||||
const Char UNTAG_SEP = _('\3');
|
||||
const Char UNTAG_ATOM_KWPPH = _('\4');
|
||||
const Char UNTAG_BULLET = _('\5');
|
||||
|
||||
/// Untag a string for use with cursors, <atom>...</atom> becomes a single character.
|
||||
/** This string should only be used for cursor position calculations. */
|
||||
@@ -179,6 +193,11 @@ size_t untagged_to_index(const String& str, size_t pos, bool inside, size_t star
|
||||
size_t index_to_untagged(const String& str, size_t index);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Global operations
|
||||
|
||||
/// Add a tag and its close tag around a string. Tag must be complete.
|
||||
String wrap_tag(const String& str, const String& tag);
|
||||
/// Add a tag and its close tag around a string but in the opposite order.
|
||||
String anti_wrap_tag(const String& str, const String& tag);
|
||||
|
||||
/// Remove all instances of a tag and its close tag, but keep the contents.
|
||||
/** tag doesn't have to be a complete tag, for example remove_tag(str, "<kw-")
|
||||
@@ -244,7 +263,9 @@ String simplify_tagged(const String& str);
|
||||
/// Simplify a tagged string by merging adjecent open/close tags
|
||||
/** e.g. "<tag></tag>" --> ""
|
||||
*
|
||||
* @param all Merge all tags, if false only merges b,i,sym, and <tag></tag> pairs. But not </tag><tag>.
|
||||
* @param all Merge all tags, if false only merges b,i,u,strike,color,size,font,sym, and <tag></tag> pairs.
|
||||
* But not </tag><tag>, as this could lead to structural changes. For example, merging </li><li> would
|
||||
* fuse two bullet points together.
|
||||
*/
|
||||
String simplify_tagged_merge(const String& str, bool all = false);
|
||||
|
||||
|
||||
@@ -134,9 +134,12 @@ enum ChildMenuID {
|
||||
ID_FORMAT_ITALIC,
|
||||
ID_FORMAT_UNDERLINE,
|
||||
ID_FORMAT_STRIKETHROUGH,
|
||||
ID_FORMAT_COLOR,
|
||||
ID_FORMAT_BULLETPOINT,
|
||||
ID_FORMAT_SYMBOL,
|
||||
ID_FORMAT_REMINDER,
|
||||
ID_INSERT_SYMBOL,
|
||||
ID_FORMAT_FONT,
|
||||
|
||||
// Spelling errors
|
||||
ID_SPELLING_ADD_TO_DICT = 6301,
|
||||
|
||||
Reference in New Issue
Block a user