Edit online comments with easy addition of HTML tags for bold, italics, underlining, blockquote and anchored links. Then check your work with the preview feature.
Requires wxWidgets.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | """
CommentEditor: Small HTML editor for online comments with preview feature.
Based on wxWidgets.
"""
__author__=["Jack Trainor (jacktrainor@gmail.com)",]
__version__="June 2009"
import sys
import os, os.path
import re
import wx, wx.html
DIALOG_WIDTH = 600
DIALOG_HEIGHT = 300
def create_button(frame, panel, buttonTitle, method, id=wx.ID_ANY):
button = wx.Button(panel, id, buttonTitle)
frame.Bind(wx.EVT_BUTTON, method, button)
return button
class PreviewHtmlWindow(wx.html.HtmlWindow):
def __init__(self, parent, id, frame):
wx.html.HtmlWindow.__init__(self,parent,id)
class PreviewPanel(wx.Panel):
def __init__(self, parent, id, frame):
wx.Panel.__init__(self, parent, id)
self.frame = frame
self.html = PreviewHtmlWindow(self, -1, self.frame)
self.box = wx.BoxSizer(wx.VERTICAL)
self.box.Add(self.html, 1, wx.GROW)
subbox = wx.BoxSizer(wx.HORIZONTAL)
self.backButton = create_button(parent, self, "Back", self.OnBack)
subbox.Add(self.backButton, 1, wx.GROW | wx.ALL, 2)
self.forwardButton = create_button(parent, self, "Forward", self.OnForward)
subbox.Add(self.forwardButton, 1, wx.GROW | wx.ALL, 2)
self.box.Add(subbox, 0, wx.GROW)
self.SetSizer(self.box)
self.SetAutoLayout(True)
def OnBack(self, event):
if not self.html.HistoryBack():
wx.MessageBox("No more items in history!")
def OnForward(self, event):
if not self.html.HistoryForward():
wx.MessageBox("No more items in history!")
class PreviewFrame(wx.Frame):
def __init__(self, app, parent, title):
self.app = app
screen_pos = parent.ScreenPosition
screen_pos.y += parent.Size.y
wx.Frame.__init__(self, parent, -1, title, screen_pos, parent.Size)
self.panel = PreviewPanel(self, wx.ID_ANY, self)
def OnTimeToClose(self, evt=None):
self.Close()
class EditorPanel(wx.Panel):
def __init__(self, parent, id=wx.ID_ANY):
wx.Panel.__init__(self, parent, id)
font = wx.Font(10, -1, wx.NORMAL, wx.FONTSTYLE_NORMAL, faceName="Courier New")
self.editText = wx.TextCtrl(self, -1, "", size=(DIALOG_WIDTH-20, DIALOG_HEIGHT-96), style=wx.TE_MULTILINE)
self.editText.SetFont(font)
self.anchorButton = create_button(parent, self, "Anchor", parent.OnAnchor)
self.anchorEntry = wx.TextCtrl(self, -1, "" , wx.DefaultPosition, wx.Size(DIALOG_WIDTH-100, -1))
self.anchorEntry.SetFont(font)
self.boldButton = create_button(parent, self, "Bold", parent.OnBold)
self.italicButton = create_button(parent, self, "Italic", parent.OnItalic)
self.blockquoteButton = create_button(parent, self, "Blockquote", parent.OnBlockquote)
self.previewButton = create_button(parent, self, "Preview", parent.OnPreview)
self.quitButton = create_button(parent, self, "Quit", parent.OnTimeToClose)
anchorSizer = wx.BoxSizer(wx.HORIZONTAL)
anchorSizer.Add(self.anchorButton, 0, wx.GROW | wx.ALL, 2)
anchorSizer.Add(self.anchorEntry, 0, wx.GROW | wx.ALL, 2)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
buttonSizer.Add(self.boldButton, 0, wx.GROW | wx.ALL, 2)
buttonSizer.Add(self.italicButton, 0, wx.GROW | wx.ALL, 2)
buttonSizer.Add(self.blockquoteButton, 0, wx.GROW | wx.ALL, 2)
buttonSizer.Add(self.previewButton, 0, wx.GROW | wx.ALL, 2)
buttonSizer.Add(self.quitButton, 0, wx.GROW | wx.ALL, 2)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.editText, 1, wx.GROW | wx.ALL, 2)
sizer.Add(anchorSizer, 0, wx.ALL, 2)
sizer.Add(buttonSizer, 0, wx.ALL, 2)
self.SetSizer(sizer)
self.Layout()
def GetText(self):
return self.editText.GetValue()
def GetAnchorText(self):
return self.anchorEntry.GetValue()
def SetText(self, text):
self.editText.SetValue(text)
self.editText.SetSelection(0, 0)
def TagSelection(self, tag, attributes={}):
from_pos, to_pos = self.editText.GetSelection()
s = self.editText.GetStringSelection()
if s:
attrs_list = []
for key, val in attributes.items():
if type(val) == str:
val = '"%s"' % (key)
attrs_list.append('%s=%s' % (key, str(val)))
open_tag = "<" + tag
if attrs_list:
open_tag += " " + " ".join(attrs_list)
open_tag += ">"
end_tag = "</" + tag + ">"
s = open_tag + s + end_tag
self.editText.Replace(from_pos, to_pos, s)
class EditorFrame(wx.Frame):
def __init__(self, app, parent, title):
self.app = app
wx.Frame.__init__(self, parent, -1, title, pos=(0, 0), size=(DIALOG_WIDTH, DIALOG_HEIGHT))
self.panel = EditorPanel(self)
self.previewFrame = None
def OnBold(self, evt):
self.panel.TagSelection("b")
def OnItalic(self, evt):
self.panel.TagSelection("i")
def OnBlockquote(self, evt):
self.panel.TagSelection("blockquote")
def OnAnchor(self, evt):
anchorText = self.panel.GetAnchorText()
if anchorText and anchorText.find("http:") == 0:
self.panel.TagSelection("a", {"href":anchorText})
def OnPreview(self, evt):
if self.previewFrame:
self.previewFrame.OnTimeToClose()
self.previewFrame = PreviewFrame(self.app, self, "Preview")
self.previewFrame.Show(True)
text = self.GetText()
text = text.replace("\n", "<br>")
text = "<html><body>" + text + "</body></html>"
self.previewFrame.panel.html.SetPage(text)
def OnTimeToClose(self, evt):
if self.previewFrame:
self.previewFrame.OnTimeToClose()
self.Close()
def GetText(self):
return self.panel.GetText()
def SetText(self, text):
self.panel.SetText(text)
class CommentEditor(wx.App):
def __init__(self, redirect=True, fileName=None):
wx.App.__init__(self, redirect, fileName)
def OnInit(self):
self.frame = EditorFrame(self, None, "Comment Editor")
self.SetTopWindow(self.frame)
self.frame.Show(True)
return True
def main():
app = CommentEditor(redirect=False)
app.MainLoop()
if __name__ == '__main__':
main()
|
Many websites allow comments but provide only a tiny window for editing. The commenter must add HTML tags by hand for emphasis and for links. Furthermore a preview is often lacking, so if a tag is wrong, the commenter doesn't see until it is too late.
This recipe is also a testament to the power of wxWidgets allowing the programmer to put together a functioning editor with a browser preview in a handful of screens.