The Plug-in Pattern derives its name from the fact that behaviour extension is plugged-into a core class. The pattern is realized by means of a single (partial) abstract class, which defines the interface between the plug-in and the core class. Specific plug-ins are created by sub-classing this class. The interface is bidirectional in the sense that it contains methods called by the core class that the plug-in should implement, and that it contains methods which the plug-in can call at the core class. It provides a clean interface in the sense that the abstract class only contains those methods that define the interface.
class AbstractSyntaxColorer { // CCrystalTextView needs to have access to some private members friend class CCrystalTextView; public: AbstractSyntaxColorer(); // Members which are access from CCrystalTextView // and which define default values COLORREF defaultTextColor; COLORREF defaultBkColor; COLORREF noTextColor; COLORREF selectTextColor; COLORREF selectBkColor; // Methods which should be implemented by derived syntax colorer virtual DWORD createParseState() { return 0; } virtual DWORD copyParseState(DWORD state) { return state; } virtual void destroyParseState(DWORD &state) { state = 0; } virtual void parseLine(const char *line, DWORD &state, int &lineFlags) = 0; // Methods which the syntax colorer can call from its implementation // of parseLine to perform the colouring void color(int begin, int end, COLORREF crText, COLORREF crBK); void startColor(int begin, COLORREF crText, COLORREF crBK); void endColor(int end); private: void drawLine(LPCTSTR line, DWORD &state, int &lineFlags); CCrystalTextView *_view; bool _activeColorRange; int _begin; COLORREF _crText; COLORREF _crBK; }; |
AbstractSyntaxColorer::AbstractSyntaxColorer() { defaultTextColor = ::GetSysColor(COLOR_WINDOWTEXT); defaultBkColor = ::GetSysColor(COLOR_WINDOW); noTextColor = defaultBkColor; selectTextColor = defaultBkColor; selectBkColor = defaultTextColor; } |
void AbstractSyntaxColorer::color(int begin, int end, COLORREF crText, COLORREF crBK) { _view->DrawLineHelper(begin, end, crText, crBK); } |
void AbstractSyntaxColorer::startColor(int begin, COLORREF crText, COLORREF crBK) { if (_activeColorRange) endColor(begin); _activeColorRange = true; _begin = begin; _crText = crText; _crBK = crBK; } |
void AbstractSyntaxColorer::endColor(int end) { if (!_activeColorRange) return; color(_begin, end, _crText, _crBK); _activeColorRange = false; } |
void AbstractSyntaxColorer::drawLine(LPCTSTR line, DWORD &state, int &lineFlags) { if (state == 0) state = createParseState(); else state = copyParseState(state); _activeColorRange = false; parseLine(line, state, lineFlags); if (_activeColorRange) endColor(strlen(line)); } |
template <class S> class AbstractStateSyntaxColorer : public AbstractSyntaxColorer { virtual void parseLine(const char *line, S& state, int &lineFlags) = 0; void parseLine(const char *line, DWORD &state, int &lineFlags) { parseLine(line, *(S*)state, lineFlags); } DWORD createParseState() { return (DWORD)new S; } DWORD copyParseState(DWORD state) { return (DWORD)new S((S*)state); } void destroyParseState(DWORD &state) { delete (S*)state; } }; |
home page | Software Engineering | My life as a hacker