Example PagePlugin:
The best way to explain this is to look at an example in detail. Before we look at code, lets look at how this plugin (PageCountPlugin) is used in a theme:
Here are two example instantiations of the PageCountPlugin (from the Dejavu theme):
<MSPlugin=PageCount
Filter=($PageFilter)
Graph.Format=Graph
Graph.Width=500 Graph.Height=300
Graph.BGColor=($BGColor)
Graph.MaxListLength=20
Graph.Java.BarColor="#0000FF"
Graph.Java.BarEndColor="#FFFF00"
Graph.Java.BarStyle=2
Graph.Java.BarCenter=128
Graph.Java.GraphWidth=500
Graph.Java.GraphHeight=300
Graph.ASCII.MaxBarLength=70
Graph.Image.MaxBarLength=500>
Although this looks complicated, it really isn't. Basically the plugin is told to use the Filter object that is passed into the theme in the PageFilter variable, and it tells the plugin to draw as a graph (the Graph.Format parameter), and explicitly tells it how to do so.
<MSPlugin=PageCount
Filter=($PageFilter)
Graph.Format=Table
Graph.MaxListLength=20
Graph.Table.ColumnHeadColor="#FFFF00">
This example is much shorter, and tells the plugin to draw in Table mode with the same filter. It also specifies a color to use in the column headers.
So now that we see how this powerful plugin is used, lets take a look at its source (this also shows an example of splitting a plugin across .h and .cpp files):
// From the PageCountPlugin.h file...
//
#include "PagePlugin.h"
#include "AccessFormatPlugin.h"
#include "Table.h"
#include "VarTable.h"
class PageCountPlugin : public PluginTemplate<PagePlugin,PageCountPlugin> {
public:
inline static unsigned int GetCurrentVersion() {
return 100; // Version 1.00
}
inline static const char *GetPluginName() {
return "PageCount";
}
PageCountPlugin(int &CE);
void ProcessAccess(AccessFormatPlugin &);
void ResetState();
void OutputHTML(ostream &, VarTable &);
void LoadState(Serialize &); // Save and restore state across program
void SaveState(Serialize &); // runs...
void GetFullName(VarTable &Params, String &FullName, int UpdateFreq);
private :
Table<String, int> CountTable; // mapping between URL and count
};
This is a pretty straightforward implementation of the interface described above. Here all that is filled in is the version and plugin name... which are trivial. Okay, lets look at the implementation file now...
// From the PageCountPlugin.cpp file...
//
#include "PageCountPlugin.h"
#include "DataGraph.h"
#include "SerializeEx.h"
// Initialize the plugin, as we discussed before...
INIT_PLUGIN(PageCountPlugin);
PageCountPlugin::PageCountPlugin(int &CE) {
Flags = FAutoFilter | FIgnoreErrors;
ResetState();
}
void PageCountPlugin::GetFullName(VarTable &Params, String &FullName,
int UpdateFreq) {
String Filt;
if (Params["Filter"] != 0) {
Filt = Params["Filter"]->GetStringValue();
} else {
Filt = DefFilter.ToParamStr();
}
FullName = String::IntToStr(UpdateFreq) + Name + "\t" + Filt;
}
void PageCountPlugin::ProcessAccess(AccessFormatPlugin &A) {
CountTable[A.GetURL()]++;
}
void PageCountPlugin::ResetState() {
CountTable.Clear(); // Free all of the data in the linked list...
CountTable.SetDefault(0);
}
void PageCountPlugin::SaveState(Serialize &O) {
O << GetCurrentVersion(); // Serialize the Version number
O << CountTable;
}
void PageCountPlugin::LoadState(Serialize &I) {
unsigned int Version = 0;
I >> Version;
// Check version number...
switch (Version) {
case 100: // Version 1.00
I >> CountTable;
break;
default:
cout << "Serialized " << Name << " Page plugin is of a version that cannot "
<< "be deserialized\nwith this version of the plugin. Reseting state.\n";
break;
}
}
void PageCountPlugin::OutputHTML(ostream &O, VarTable &Params) {
DataGraph Data(Params);
typedef DataPair<String,int> Pair;
LinkedList<Pair> List;
LinkedList<String> RowLabels, Pages, Count;
// Copy the data from the table into the linked list...
CountTable.ConvertToList(List);
// Sort the data list by the number of hits.
List.Sort(&Pair;::SortBySecondary);
// Go through the list and convert URL's to links...
LinkedList<Pair>::Iterator I = List.GetIterator();
while (I) {
String &URL = I->P;
URL = "<a href='" + URL + "'>" + URL + "</a>";
I++;
}
Data.SetRowLabelFormat(1); // Increasing integer labels
Data.SetRowLabels(RowLabels);
Data.AddColumn(Pages);
Data.AddColumn(Count);
RowLabels.AddToTail("#");
Pages.AddToTail("Web Page URL:");
Count.AddToTail("Hits:");
I = List.GetIterator();
while (I) {
Pages.AddToTail(I->P);
Count.AddToTail(String::IntToStr(I->S));
I++;
}
Data.WriteHTML(O);
}