How can I add support for new tags

The cells returned by the parser are created internally by tag handlers, a pluggable structure by which HTML tags are associated with the creation and manipulation of the HTML parser cells. You can create your own tag handlers and associate them with HTML tags. With this mechanism you can extend the HTML window to include standard tags not currently supported, or custom tags of your own invention. Figure 16.4 displays the use of a custom HTML tag.

Custom HTML Tag Handler

Tira

This silly example shows how custom tags can be defined and used in a wx.HtmlWindow. We've defined a new tag, <blue> that will change the foreground color of the portions of the document that it encloses to some shade of blue. The tag handler can also use parameters specifed in the tag, for example:

♦ Midnight Blue

Figure 16.4

A wx.HtmlWindow using a custom tag handler

Listing 16.4 displays the code used to produce figure 16.4.

Listing 16.4 Defining and using a custom tag handler import wx import wx.html page = <html><body>

This silly example shows how custom tags can be defined and used in a wx.HtmlWindow. We've defined a new tag, &lt;blue&gt; that will change the <blue>foreground color</blue> of the portions of the document that it encloses to some shade of blue. The tag handler can also use parameters specified in the tag, for example:

<li> <blue shade='sky'>Sky Blue</blue>

<li> <blue shade='midnight'>Midnight Blue</blue>

<li> <blue shade='dark'>Dark Blue</blue>

<li> <blue shade='navy'>Navy Blue</blue>

class BlueTagHandler(wx.html.HtmlWinTagHandler):

tag handler

wx.html.HtmlWinTagHandler._init_(self)

def GetSupportedTags(self):

Defining tags that return "BLUE" 1 are handled def HandleTag(self, tag): <— Handling the tag old = self.GetParser().GetActualColor() clr = "#0000FF" if tag.HasParam("SHADE"):

shade = tag.GetParam("SHADE") if shade.upper() == "SKY":

clr = "#3299CC" if shade.upper() == "MIDNIGHT":

clr = "#2F2F4F" elif shade.upper() == "DARK":

clr = "#00008B" elif shade.upper == "NAVY": clr = "#23238E"

self.GetParser().SetActualColor(clr) container = self.GetParser().GetContainer() container.InsertCell(wx.html.HtmlColourCell(clr)) self.ParseInner(tag)

self.GetParser().SetActualColor(old) container = self.GetParser().GetContainer() container.InsertCell(wx.html.HtmlColourCell(old)) return True wx.html.HtmlWinParser_AddTagHandler(BlueTagHandler) <1—i Telling the parser class MyHtmlFrame(wx.Frame): '

html = wx.html.HtmlWindow(self) if "gtk2" in wx.PlatformInfo:

html.SetStandardFonts() html.SetPage(page)

app = wx.PySimpleApp()

frm = MyHtmlFrame(None, "Custom HTML Tag Handler") frm.Show() app.MainLoop()

about the handler

The tags themselves are represented internally as methods of the class wx.Html. Tag, which is created by the HTML parser. Typically, you won't need to create your own instances. Table 16.4 displays the wx.Html.Tag class with methods that are useful to retrieve information about the tags.

Table 16.4 Some methods of wx.Html.Tag

Method

Description

GetAllParams()

Returns all the parameters associated with the tag as a string. For some purposes, it might be easier to parse this string rather than get each parameter individually.

GetName()

Returns the tag name, in uppercase text.

HasParam(param)

Returns True if the tag has the given parameter.

GetParam(param, with_commas=False)

Returns the value of the parameter param. If the with_commas parameter is True, you get a raw string including the quotation marks starting and ending the value, if any. Returns an empty string if the parameter doesn't exist. The related method GetParamAsColour(param) returns the parameter value as a wx.Color, and the method GetParamAslnt(param) returns the value as an int.

HasEnding()

Returns True if the tag has an ending tag, and false otherwise.

A tag handler used for extending the HTML window is a subclass of wx.html. HtmlWinTagHandler. Your subclass needs to override two methods, and needs to be aware of one further method. The first method to override is GetSupported-Tags(). This method returns the list of tags that are managed by this handler. The tags must be in uppercase, and if there is more than one they are separated by a comma, with no spaces in between, as in the following example.

GetSupportedTags(self):

return "MYTAG,MYTAGPARAM"

The second method that you need to override is HandleTag(tag). Within the HandleTag method, you handle the tag by adding new cell elements to the parser (or alternately making changes to the container cell that the parser has open at that point). You get the parser by calling the GetParser() method of the tag handler. To write a HandleTag() method, you should:

1 Get the parser.

2 Process the parameters to your tag as necessary, possibly making changes to or creating a new cell.

3 If the tag being parsed is a begin/end pair with inner text, parse the text in between.

4 Perform any cleanup needed to the parser.

As mentioned, you get the parser with GetParser(). To add or edit cells in the parser, you have three options. First, if you want to add another cell to the container, you can work with the current container. Next, you call the parser's Get-Container() method, then create your wx.html.HTMLCell subclass instance by whatever means you want, and add it to the container by calling the container's InsertCell(cell) method.

Occasionally, you'll want to create a container that is subordinate or nested within the currently open container. One example might be a table cell that is nested within a table row. To do this, you need to call the parser method OpenCon-tainer(). This method returns your new container cell, into which you can insert display cells with the InsertCell(cell) method. For every container you open in your tag handler, you are expected to close it using the CloseContainer() method. If you do not have a balance between your OpenContainer() and Close-Container() calls, it will disrupt the parser behavior on the rest of the HTML text.

Another option is to create a container at the same level as the parser's current container, meaning that you aren't nesting containers. An example would be a new paragraph—it's not part of the previous paragraph, nor is it subordinate to it; it's a new entity in the page. In order to get that behavior in the parse, you need to close the existing container, open a new container, and reverse the process at the end of the method.

parser = self.GetParser()

parser.CloseContainer()

parser.OpenContainer()

# Do all your stuff parser.CloseContainer() parser.OpenContainer()

This has the effect of giving you a new container to put your information into, but ensuring that the parser has a clean container at the same nesting depth that existed at the beginning of the method.

Was this article helpful?

0 0

Post a comment