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