mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
find/replace kind of working
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@299 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -94,6 +94,29 @@ class TextToggleReminderAction : public ValueAction {
|
||||
Char old; ///< Old value of the <kw- tag
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Replace all
|
||||
|
||||
/// A TextValueAction without the start and end stuff
|
||||
class SimpleTextValueAction : public ValueAction {
|
||||
public:
|
||||
SimpleTextValueAction(const TextValueP& value, const Defaultable<String>& new_value);
|
||||
virtual void perform(bool to_undo);
|
||||
bool merge(const SimpleTextValueAction& action);
|
||||
private:
|
||||
Defaultable<String> new_value;
|
||||
};
|
||||
|
||||
/// An action from "Replace All"; just a bunch of value actions performed in sequence
|
||||
class ReplaceAllAction : public Action {
|
||||
public:
|
||||
~ReplaceAllAction();
|
||||
|
||||
virtual String getName(bool to_undo) const;
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
vector<SimpleTextValueAction> actions;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Event
|
||||
|
||||
/// Notification that a script caused a value to change
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <data/field.hpp>
|
||||
#include <data/stylesheet.hpp>
|
||||
#include <data/settings.hpp>
|
||||
#include <util/find_replace.hpp>
|
||||
#include <wx/caret.h>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(ValueViewerP);
|
||||
@@ -133,6 +134,22 @@ void DataEditor::onInit() {
|
||||
current_viewer = nullptr;
|
||||
current_editor = nullptr;
|
||||
}
|
||||
// ----------------------------------------------------------------------------- : Search / replace
|
||||
|
||||
bool DataEditor::search(FindInfo& find, bool from_start) {
|
||||
bool include = from_start;
|
||||
for (size_t i = 0 ; i < by_tab_index.size() ; ++i) {
|
||||
ValueViewer& viewer = *by_tab_index[find.forward() ? i : by_tab_index.size() - i - 1];
|
||||
if (&viewer == current_viewer) include = true;
|
||||
if (include) {
|
||||
ValueEditor* editor = viewer.getEditor();
|
||||
if (editor && editor->search(find, from_start || &viewer != current_viewer)) {
|
||||
return true; // done
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // not done
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Clipboard & Formatting
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class DataEditor : public CardViewer {
|
||||
/** If from_start == false: searches only from the current selection onward (or backward)
|
||||
* If from_start == true: searches everything
|
||||
*
|
||||
* Returns true when more searching is needed.
|
||||
* Returns true if we are done and searching should be ended.
|
||||
*/
|
||||
bool search(FindInfo& find, bool from_start);
|
||||
|
||||
|
||||
@@ -69,11 +69,12 @@ class CardListBase : public ItemList, public SetView {
|
||||
virtual void onAction(const Action&, bool undone);
|
||||
|
||||
// --------------------------------------------------- : The cards
|
||||
public:
|
||||
/// Return the card at the given position in the sorted card list
|
||||
inline CardP getCard(long pos) const { return static_pointer_cast<Card>(getItem(pos)); }
|
||||
protected:
|
||||
/// Get a list of all cards
|
||||
virtual void getItems(vector<VoidP>& out) const;
|
||||
/// Return the card at the given position in the sorted card list
|
||||
inline CardP getCard(long pos) const { return static_pointer_cast<Card>(getItem(pos)); }
|
||||
|
||||
/// Rebuild the card list (clear all vectors and fill them again)
|
||||
void rebuild();
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <data/card.hpp>
|
||||
#include <data/action/set.hpp>
|
||||
#include <data/settings.hpp>
|
||||
#include <util/find_replace.hpp>
|
||||
#include <util/tagged_string.hpp>
|
||||
#include <util/window_id.hpp>
|
||||
#include <wx/splitter.h>
|
||||
|
||||
@@ -266,6 +268,61 @@ void CardsPanel::doPaste() { CUT_COPY_PASTE(doPaste, ;) }
|
||||
|
||||
// ----------------------------------------------------------------------------- : Searching
|
||||
|
||||
class CardsPanel::SearchFindInfo : public FindInfo {
|
||||
public:
|
||||
SearchFindInfo(CardsPanel& panel, wxFindReplaceData& what) : FindInfo(what), panel(panel) {}
|
||||
virtual bool handle(const CardP& card, const TextValueP& value, size_t pos) {
|
||||
// Select the card
|
||||
panel.card_list->setCard(card);
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
CardsPanel& panel;
|
||||
};
|
||||
|
||||
class CardsPanel::ReplaceFindInfo : public FindInfo {
|
||||
public:
|
||||
ReplaceFindInfo(CardsPanel& panel, wxFindReplaceData& what) : FindInfo(what), panel(panel) {}
|
||||
virtual bool handle(const CardP& card, const TextValueP& value, size_t pos) {
|
||||
// Select the card
|
||||
panel.card_list->setCard(card);
|
||||
// Replace
|
||||
panel.editor->insert(escape(what.GetReplaceString()), _("Replace"));
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
CardsPanel& panel;
|
||||
};
|
||||
|
||||
bool CardsPanel::doFind(wxFindReplaceData& what) {
|
||||
SearchFindInfo find(*this, what);
|
||||
return search(find, false);
|
||||
}
|
||||
bool CardsPanel::doReplace(wxFindReplaceData& what) {
|
||||
ReplaceFindInfo find(*this, what);
|
||||
return search(find, false);
|
||||
}
|
||||
bool CardsPanel::doReplaceAll(wxFindReplaceData& what) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool CardsPanel::search(FindInfo& find, bool from_start) {
|
||||
bool include = from_start;
|
||||
CardP current = card_list->getCard();
|
||||
for (size_t i = 0 ; i < set->cards.size() ; ++i) {
|
||||
CardP card = card_list->getCard( (long) (find.forward() ? i : set->cards.size() - i - 1) );
|
||||
if (card == current) include = true;
|
||||
if (include) {
|
||||
editor->setCard(card);
|
||||
if (editor->search(find, from_start || card != current)) {
|
||||
return true; // done
|
||||
}
|
||||
}
|
||||
}
|
||||
editor->setCard(current);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Selection
|
||||
|
||||
CardP CardsPanel::selectedCard() const {
|
||||
|
||||
+13
-33
@@ -18,6 +18,7 @@ class DataEditor;
|
||||
class TextCtrl;
|
||||
class IconMenu;
|
||||
class HoverButton;
|
||||
class FindInfo;
|
||||
|
||||
// ----------------------------------------------------------------------------- : CardsPanel
|
||||
|
||||
@@ -39,7 +40,6 @@ class CardsPanel : public SetWindowPanel {
|
||||
// --------------------------------------------------- : Actions
|
||||
|
||||
virtual bool wantsToHandle(const Action&, bool undone) const;
|
||||
public:
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
virtual bool canCut() const;
|
||||
@@ -50,39 +50,19 @@ class CardsPanel : public SetWindowPanel {
|
||||
virtual void doPaste();
|
||||
|
||||
// --------------------------------------------------- : Searching (find/replace)
|
||||
#if 0
|
||||
virtual bool canFind() const;
|
||||
virtual bool canReplace() const;
|
||||
virtual bool doFind(wxFindReplaceData& what);
|
||||
virtual bool doReplace(wxFindReplaceData& what);
|
||||
|
||||
virtual bool canFind() const { return true; }
|
||||
virtual bool canReplace() const { return true; }
|
||||
virtual bool doFind (wxFindReplaceData&);
|
||||
virtual bool doReplace (wxFindReplaceData&);
|
||||
virtual bool doReplaceAll(wxFindReplaceData&);
|
||||
private:
|
||||
// Functions that handle finding
|
||||
typedef void (CardsPanel::*FindHandler)(const CardP&, const TextValueP&, const size_t, const size_t, wxFindReplaceData&);
|
||||
|
||||
/// Execute a find (or replace), and start with the currently selected card and value
|
||||
/** if findSame==true then find will also find the currently highlighted word
|
||||
* Returns true if found
|
||||
*/
|
||||
bool find(FindReplaceData& what, const FindHandler& handler, bool findSame = false);
|
||||
|
||||
/// find handler : select found value
|
||||
void handleFind(const CardP& card, const TextValueP& value, size_t start, size_t end, FindReplaceData& what);
|
||||
|
||||
/// replace handler : replace found value, move selection to end
|
||||
void handleReplace(const CardP& card, const TextValueP& value, size_t start, size_t end, FindReplaceData& what);
|
||||
|
||||
/// Find in all cards
|
||||
/** NOTE: this function is essentially the same as findInCard */
|
||||
bool findInCards(const CardP& firstCard, const ValueP& firstValue, int firstChar, FindReplaceData& what, const FindHandler& handler);
|
||||
|
||||
/// Find in a card, if firstValue is specified start searching there
|
||||
/** NOTE: this function is essentially the same as findInCards */
|
||||
bool findInCard(const CardP& card, const ValueP& firstValue, int firstChar, FindReplaceData& what, const FindHandler& handler);
|
||||
|
||||
/// Find the current search string in the specified value
|
||||
/** if searchDir = up searches from the end and only before firstChar, unless firstChar == -1 */
|
||||
bool findInValue(const CardP& crd_, virtual const ValueP& value, int firstChar, FindReplaceData& what, const FindHandler& handler);
|
||||
#endif
|
||||
/// Do a search or replace action for the given FindInfo in all cards
|
||||
bool search(FindInfo& find, bool from_start);
|
||||
class SearchFindInfo;
|
||||
class ReplaceFindInfo;
|
||||
friend class CardsPanel::SearchFindInfo;
|
||||
friend class CardsPanel::ReplaceFindInfo;
|
||||
public:
|
||||
|
||||
// --------------------------------------------------- : Selection
|
||||
|
||||
@@ -61,8 +61,9 @@ class SetWindowPanel : public wxPanel, public SetView {
|
||||
// --------------------------------------------------- : Searching (find/replace)
|
||||
virtual bool canFind() const { return false; } ///< Is finding possible?
|
||||
virtual bool canReplace() const { return false; } ///< Is replacing possible?
|
||||
virtual bool doFind(wxFindReplaceData&) { return false; } ///< Find the next math
|
||||
virtual bool doReplace(wxFindReplaceData&) { return false; } ///< Replace the next match
|
||||
virtual bool doFind (wxFindReplaceData&) { return false; } ///< Find the next math
|
||||
virtual bool doReplace (wxFindReplaceData&) { return false; } ///< Replace the next match
|
||||
virtual bool doReplaceAll(wxFindReplaceData&) { return false; } ///< Replace all matches
|
||||
|
||||
// --------------------------------------------------- : Selection
|
||||
virtual CardP selectedCard() const { return CardP(); } ///< Return the currently selected card, or CardP()
|
||||
|
||||
@@ -43,6 +43,7 @@ SetWindow::SetWindow(Window* parent, const SetP& set)
|
||||
: wxFrame(parent, wxID_ANY, _TITLE_("magic set editor"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
, current_panel(nullptr)
|
||||
, find_dialog(nullptr)
|
||||
, find_data(wxFR_DOWN)
|
||||
, number_of_recent_sets(0)
|
||||
{
|
||||
SetIcon(load_resource_icon(_("app")));
|
||||
@@ -537,7 +538,7 @@ void SetWindow::onReplace (wxFindDialogEvent&) {
|
||||
current_panel->doReplace(find_data);
|
||||
}
|
||||
void SetWindow::onReplaceAll(wxFindDialogEvent&) {
|
||||
// todo
|
||||
current_panel->doReplaceAll(find_data);
|
||||
}
|
||||
|
||||
void SetWindow::onEditPreferences(wxCommandEvent&) {
|
||||
@@ -627,10 +628,10 @@ BEGIN_EVENT_TABLE(SetWindow, wxFrame)
|
||||
EVT_GALLERY_SELECT (ID_FIELD_LIST, SetWindow::onChildMenu) // for StatsPanel, because it is not a EVT_TOOL
|
||||
|
||||
EVT_UPDATE_UI (wxID_ANY, SetWindow::onUpdateUI)
|
||||
// EVT_FIND (wxID_ANY, SetWindow::onFind)
|
||||
// EVT_FIND_NEXT (wxID_ANY, SetWindow::onFindNext)
|
||||
// EVT_FIND_REPLACE (wxID_ANY, SetWindow::onReplace)
|
||||
// EVT_FIND_REPLACE_ALL(wxID_ANY, SetWindow::onReplaceAll)
|
||||
EVT_FIND (wxID_ANY, SetWindow::onFind)
|
||||
EVT_FIND_NEXT (wxID_ANY, SetWindow::onFindNext)
|
||||
EVT_FIND_REPLACE (wxID_ANY, SetWindow::onReplace)
|
||||
EVT_FIND_REPLACE_ALL(wxID_ANY, SetWindow::onReplaceAll)
|
||||
EVT_CLOSE ( SetWindow::onClose)
|
||||
EVT_IDLE ( SetWindow::onIdle)
|
||||
EVT_CARD_SELECT (wxID_ANY, SetWindow::onCardSelect)
|
||||
|
||||
@@ -106,9 +106,9 @@ class ValueEditor {
|
||||
* excluding the sellection itself.
|
||||
* If from_start == true: searches everything
|
||||
*
|
||||
* Returns true when more searching is needed.
|
||||
* Returns true if we are done and searching should be ended.
|
||||
*/
|
||||
bool search(FindInfo& find, bool from_start);
|
||||
virtual bool search(FindInfo& find, bool from_start) { return false; }
|
||||
|
||||
// --------------------------------------------------- : Other
|
||||
|
||||
|
||||
+57
-1
@@ -11,6 +11,7 @@
|
||||
#include <gui/util.hpp>
|
||||
#include <data/action/value.hpp>
|
||||
#include <util/tagged_string.hpp>
|
||||
#include <util/find_replace.hpp>
|
||||
#include <util/window_id.hpp>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/caret.h>
|
||||
@@ -195,7 +196,8 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (ev.GetKeyCode() >= _(' ') /*&& ev.GetKeyCode() == (int)ev.GetRawKeyCode()*/) {
|
||||
// if (ev.GetKeyCode() >= _(' ') /*&& ev.GetKeyCode() == (int)ev.GetRawKeyCode()*/) {
|
||||
if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) {
|
||||
// TODO: Find a more correct way to determine normal characters,
|
||||
// this might not work for internationalized input.
|
||||
// It might also not be portable!
|
||||
@@ -656,6 +658,60 @@ size_t TextValueEditor::move(size_t pos, size_t start, size_t end, Movement dir)
|
||||
else return start;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Search / replace
|
||||
|
||||
bool is_word_end(const String& s, size_t pos) {
|
||||
if (pos == 0 || pos >= s.size()) return true;
|
||||
Char c = s.GetChar(pos);
|
||||
return isSpace(c) || isPunct(c);
|
||||
}
|
||||
|
||||
// is find.findString() at postion pos of s
|
||||
bool TextValueEditor::matchSubstr(const String& s, size_t pos, FindInfo& find) {
|
||||
if (find.wholeWord()) {
|
||||
if (!is_word_end(s, pos - 1) || !is_word_end(s, pos + find.findString().size())) return false;
|
||||
}
|
||||
if (find.caseSensitive()) {
|
||||
if (!is_substr(s, pos, find.findString())) return false;
|
||||
} else {
|
||||
if (!is_substr(s, pos, find.findString().Lower())) return false;
|
||||
}
|
||||
// handle
|
||||
if (find.select()) {
|
||||
editor().select(this);
|
||||
editor().SetFocus();
|
||||
selection_start_i = untagged_to_index(value().value(), pos, true);
|
||||
selection_end_i = untagged_to_index(value().value(), pos + find.findString().size(), true);
|
||||
fixSelection(TYPE_INDEX);
|
||||
}
|
||||
if (find.handle(viewer.getCard(), valueP(), pos)) {
|
||||
return true;
|
||||
} else {
|
||||
// TODO: string might have changed when doing replace all
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TextValueEditor::search(FindInfo& find, bool from_start) {
|
||||
String v = untag(value().value());
|
||||
if (!find.caseSensitive()) v.LowerCase();
|
||||
if (find.forward()) {
|
||||
size_t start = min(v.size(), max(selection_start, selection_end));
|
||||
size_t end = max(0, (int)v.size() - (int)find.findString().size());
|
||||
for (size_t i = start ; i <= end ; ++i) {
|
||||
if (matchSubstr(v, i, find)) return true;
|
||||
}
|
||||
} else {
|
||||
size_t start = 0;
|
||||
int end = (int)min(selection_start, selection_end) - (int)find.findString().size();
|
||||
if (end < 0) return false;
|
||||
for (size_t i = end ; i >= start ; --i) {
|
||||
if (matchSubstr(v, i, find)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Native look / scrollbar
|
||||
|
||||
void TextValueEditor::determineSize(bool force_fit) {
|
||||
|
||||
+7
-18
@@ -15,24 +15,6 @@
|
||||
#include <render/value/text.hpp>
|
||||
|
||||
class TextValueEditorScrollBar;
|
||||
class wxFindReplaceData;
|
||||
DECLARE_POINTER_TYPE(Card);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Search/replace
|
||||
|
||||
/// Information for search/replace
|
||||
class FindInfo {
|
||||
public:
|
||||
FindInfo(wxFindReplaceData& what) : what(what) {}
|
||||
virtual ~FindInfo() {}
|
||||
|
||||
/// Handle that a match was found.
|
||||
/** Should return whether more searching is needed.
|
||||
*/
|
||||
virtual bool handle(const CardP& card, const TextValueP& value, size_t start, size_t end) = 0;
|
||||
|
||||
wxFindReplaceData& what; ///< What to search for, the direction to search in
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : TextValueEditor
|
||||
|
||||
@@ -94,6 +76,13 @@ class TextValueEditor : public TextValueViewer, public ValueEditor {
|
||||
|
||||
virtual void insert(const String& text, const String& action_name);
|
||||
|
||||
// --------------------------------------------------- : Search/replace
|
||||
|
||||
virtual bool search(FindInfo& find, bool from_start);
|
||||
private:
|
||||
bool matchSubstr(const String& s, size_t pos, FindInfo& find);
|
||||
public:
|
||||
|
||||
// --------------------------------------------------- : Other
|
||||
|
||||
virtual wxCursor cursor() const;
|
||||
|
||||
+5
-2
@@ -1919,6 +1919,9 @@
|
||||
<File
|
||||
RelativePath=".\util\defaultable.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\util\find_replace.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\util\index_map.hpp">
|
||||
</File>
|
||||
@@ -2930,10 +2933,10 @@
|
||||
RelativePath="..\conversion-todo.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\data\en.mse-locale\locale">
|
||||
RelativePath="..\data\nl.mse-locale\locale">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\data\nl.mse-locale\locale">
|
||||
RelativePath="..\data\en.mse-locale\locale">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp">
|
||||
|
||||
@@ -68,7 +68,8 @@ Rotation DataViewer::getRotation() const {
|
||||
// ----------------------------------------------------------------------------- : Setting data
|
||||
|
||||
void DataViewer::setCard(const CardP& card) {
|
||||
if (!card) return; // TODO: clear vie?
|
||||
if (!card) return; // TODO: clear viewer?
|
||||
if (this->card == card) return; // already set
|
||||
assert(set);
|
||||
this->card = card;
|
||||
stylesheet = set->stylesheetFor(card);
|
||||
|
||||
@@ -317,7 +317,7 @@ void TextViewer::prepareLines(RotatedDC& dc, const String& text, const TextStyle
|
||||
vector<CharInfo> chars;
|
||||
scale = 1;
|
||||
double min_scale = elements.minScale();
|
||||
double scale_step = max(0.1,elements.scaleStep());
|
||||
double scale_step = max(0.05,elements.scaleStep());
|
||||
while (true) {
|
||||
double next_scale = scale - scale_step;
|
||||
bool last = next_scale < min_scale;
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ void handle_error(const String& e, bool allow_duplicate = true, bool now = true)
|
||||
// TODO: thread safety
|
||||
if (!allow_duplicate) {
|
||||
FOR_EACH(pe, previous_errors) {
|
||||
if (e == pe) return;
|
||||
if (e == pe) return;
|
||||
}
|
||||
previous_errors.push_back(e);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ inline bool isDigit(Char c) { return IF_UNICODE( iswdigit(c) , isdigit(c) ); }
|
||||
inline bool isAlnum(Char c) { return IF_UNICODE( iswalnum(c) , isalnum(c) ); }
|
||||
inline bool isUpper(Char c) { return IF_UNICODE( iswupper(c) , isupper(c) ); }
|
||||
inline bool isLower(Char c) { return IF_UNICODE( iswlower(c) , islower(c) ); }
|
||||
inline bool isPunct(Char c) { return IF_UNICODE( iswpunct(c) , ispunct(c) ); }
|
||||
// Character conversions
|
||||
inline Char toUpper(Char c) { return IF_UNICODE( towupper(c) , toupper(c) ); }
|
||||
inline Char toLower(Char c) { return IF_UNICODE( towlower(c) , tolower(c) ); }
|
||||
|
||||
Reference in New Issue
Block a user