class RichTextEditor(Composite): def run(self): try: self.getSelection() rng = Selection.getRange() if (self.m_timerRange is None) or (not self.m_timerRange.equals(rng)): self.onSelectionChange(rng) self.m_timerRange = rng except: GWT.log("Error in timer selection", ex) def __init__(self): Composite.__init__(self) self.m_isInText = False self.m_lastText = "" self.trigger = False self.m_lastRange = None # Timer for trying real time selection change stuff self.m_timerRange = None self.m_selTimer = Timer() self.m_mainPanel = DockPanel() self.m_toolbarPanel = HorizontalPanel() self.m_toolbarPanel.setWidth("100%") self.m_toolbarPanel.setHeight("25px") self.m_toolbarPanel.setBorderWidth(1) self.m_toolbarPanel.addStyleName("timeline-RichTextToolbar") self.m_textW = RichTextArea() self.m_textW.addClickListener(self) self.m_textW.addKeyboardListener(self) self.m_textW.addFocusListener(self) self.m_textW.addMouseListener(self) # According to gwt doc, these do need to be set because this is a frame self.m_textW.setHeight("100%") self.m_textW.setWidth("100%") # Add buttons self.m_formatter = self.getFormatter() self.m_boldW = self.addToggleButton(self.m_toolbarPanel, Icons.bold_icon, "Bold") self.m_italicW = self.addToggleButton(self.m_toolbarPanel, Icons.italics_icon, "Italic") self.m_underlineW = self.addToggleButton(self.m_toolbarPanel, Icons.underline_icon, "Underline") self.m_subscriptW = self.addToggleButton(self.m_toolbarPanel, Icons.subscript_icon, "Subscript") self.m_superscriptW = self.addToggleButton(self.m_toolbarPanel, Icons.superscript_icon, "Superscript") self.m_strikethroughW = self.addToggleButton(self.m_toolbarPanel, Icons.strikethrough_icon, "Strikethrough") self.m_indentW = self.addPushButton(self.m_toolbarPanel, Icons.indentmore_icon, "Indent Right") self.m_outdentW = self.addPushButton(self.m_toolbarPanel, Icons.indentless_icon, "Indent Left") self.m_justifyLeftW = self.addPushButton(self.m_toolbarPanel, Icons.justifyleft_icon, "Justify Left") self.m_justifyCenterW = self.addPushButton(self.m_toolbarPanel, Icons.justifycenter_icon, "Justify Center") self.m_justifyRightW = self.addPushButton(self.m_toolbarPanel, Icons.justifyright_icon, "Justify Right") self.m_hrW = self.addPushButton(self.m_toolbarPanel, Icons.horizontalrule_icon, "Horizontal Rule") self.m_olW = self.addPushButton(self.m_toolbarPanel, Icons.numberedlist_icon, "Numbered List") self.m_ulW = self.addPushButton(self.m_toolbarPanel, Icons.list_icon, "List") self.m_newLinkW = self.addPushButton(self.m_toolbarPanel, Icons.link_icon, "Link Document") self.m_removeFormatW = self.addPushButton(self.m_toolbarPanel, Icons.noformat_icon, "No Format") self.m_mainPanel.add(self.m_toolbarPanel, DockPanel.NORTH) self.m_mainPanel.add(self.m_textW, DockPanel.CENTER) self.initWidget(self.m_mainPanel) self.sinkEvents(Event.ONCLICK) def getFormatter(self): return self.m_textW.getExtendedFormatter() def getRichTextArea(self): return self.m_textW def addPushButton(self, panel, imagep, tip): img = Image(imagep) img.setWidth("20px") img.setHeight("20px") pb = PushButton(img) self.addAnyButton(panel, pb, tip) return pb def addToggleButton(self, panel, imagep, tip): img = Image(imagep) img.setWidth("20px") img.setHeight("20px") tb = ToggleButton(img) self.addAnyButton(panel, tb, tip) return tb def addAnyButton(self, panel, button, tip): button.addStyleName("richText-button") button.setTitle(tip) button.setWidth(BUTTON_WIDTH) button.setHeight("100%") panel.add(button) panel.setCellWidth(button, BUTTON_WIDTH) button.addClickListener(self) def onClick(self, sender): if sender == self.m_boldW: self.m_formatter.toggleBold() elif sender == self.m_italicW: self.m_formatter.toggleItalic() elif sender == self.m_underlineW: self.m_formatter.toggleUnderline() elif sender == self.m_subscriptW: self.m_formatter.toggleSubscript() elif sender == self.m_superscriptW: self.m_formatter.toggleSuperscript() elif sender == self.m_strikethroughW: self.m_formatter.toggleStrikethrough() elif sender == self.m_indentW: self.m_formatter.rightIndent() elif sender == self.m_outdentW: self.m_formatter.leftIndent() elif sender == self.m_justifyLeftW: self.m_formatter.setJustification(RichTextArea.Justification.LEFT) elif sender == self.m_justifyCenterW: self.m_formatter.setJustification( RichTextArea.Justification.CENTER) elif sender == self.m_justifyRightW: self.m_formatter.setJustification(RichTextArea.Justification.RIGHT) elif sender == self.m_hrW: self.m_formatter.insertHorizontalRule() elif sender == self.m_olW: self.m_formatter.insertOrderedList() elif sender == self.m_ulW: self.m_formatter.insertUnorderedList() elif sender == self.m_removeFormatW: self.m_formatter.removeFormat() elif sender == self.m_newLinkW: EventLinkPopup.open(self) elif sender == self.m_textW: self.updateStatus() self.checkForChange() def onKeyDown(self, sender, keycode, modifiers): pass def onKeyUp(self, sender, keycode, modifiers): if sender == self.m_textW: self.updateStatus() self.checkForChange() def onMouseLeave(self, event): pass def onMouseEnter(self, event): pass def onMouseUp(self, event, x, y): pass def onMouseMove(self, event, x, y): pass def onMouseDown(self, event, x, y): self.trigger = True def onFocus(self, event): pass def onLostFocus(self, event): self.checkForChange() def onMouseOut(self, event): if self.m_isInText and self.isOnTextBorder(event): self.m_isInText = False self.captureSelection() self.endSelTimer() def onMouseOver(self, event): if not self.m_isInText: self.m_isInText = True self.m_textW.setFocus(True) self.m_lastRange = None self.startSelTimer() """* * This captures the selection when the mouse leaves the RTE, because in IE * the selection indicating the cursor position is lost once another widget * gains focus. Could be implemented for IE only. """ def captureSelection(self): try: self.getSelection() self.m_lastRange = Selection.getRange() except: GWT.log("Error capturing selection for IE", ex) # Gets run every time the selection is changed def onSelectionChange(self, sel): pass def isOnTextBorder(self, event): sender = event.getSource() twX = self.m_textW.getAbsoluteLeft() twY = self.m_textW.getAbsoluteTop() x = event.getClientX() - twX y = event.getClientY() - twY width = self.m_textW.getOffsetWidth() height = self.m_textW.getOffsetHeight() return ((sender == self.m_textW) and ((x <= 0) or (x >= width) or (y <= 0) or (y >= height))) def startSelTimer(self): self.m_selTimer.scheduleRepeating(250) def endSelTimer(self): self.m_selTimer.cancel() def getRange(self): if self.m_lastRange is None: self.getSelection() return Selection.getRange() else: return self.m_lastRange def getSelection(self): res = None try: window = self.getWindow() Selection.getSelection(window) except: print "Error getting the selection" traceback.print_exc() def getWindow(self, iFrame=None): if iFrame is None: iFrame = self.m_textW.getElement() iFrameWin = iFrame.contentWindow or iFrame.contentDocument if not iFrameWin.document: iFrameWin = iFrameWin.parentNode # FBJS version of parentNode #print "getWindow", iFrameWin, dir(iFrameWin) return iFrameWin def getDocument(self): return Selection.getDocument(self.getWindow()) def setHtml(self, text): self.m_textW.setHTML(text) self.m_lastText = text def getHtml(self): return self.m_textW.getHTML() def checkForChange(self): text = self.m_textW.getHTML() if text != self.m_lastText: nEvt = doc().createEvent("HTMLEvents") nEvt.initEvent("change", False, True) self.getElement().dispatchEvent(nEvt) self.m_lastText = text # Update edit buttons based on current cursor location def updateStatus(self): if self.m_formatter is None: return self.m_boldW.setDown(self.m_formatter.isBold()) self.m_italicW.setDown(self.m_formatter.isItalic()) self.m_underlineW.setDown(self.m_formatter.isUnderlined()) self.m_subscriptW.setDown(self.m_formatter.isSubscript()) self.m_superscriptW.setDown(self.m_formatter.isSuperscript()) self.m_strikethroughW.setDown(self.m_formatter.isStrikethrough()) def addChangeHandler(self, handler): return addDomHandler(handler, ChangeEvent.getType())
class RichTextEditor(Composite): def run(self): try: self.getSelection() rng = Selection.getRange() if (self.m_timerRange is None) or (not self.m_timerRange.equals(rng)): self.onSelectionChange(rng) self.m_timerRange = rng except: GWT.log("Error in timer selection", ex) def __init__(self): Composite.__init__(self) self.m_isInText = False self.m_lastText = "" self.trigger = False self.m_lastRange = None # Timer for trying real time selection change stuff self.m_timerRange = None self.m_selTimer = Timer() self.m_mainPanel = DockPanel() self.m_toolbarPanel = HorizontalPanel() self.m_toolbarPanel.setWidth("100%") self.m_toolbarPanel.setHeight("25px") self.m_toolbarPanel.setBorderWidth(1) self.m_toolbarPanel.addStyleName("timeline-RichTextToolbar") self.m_textW = RichTextArea() self.m_textW.addClickListener(self) self.m_textW.addKeyboardListener(self) self.m_textW.addFocusListener(self) self.m_textW.addMouseListener(self) # According to gwt doc, these do need to be set because this is a frame self.m_textW.setHeight("100%") self.m_textW.setWidth("100%") # Add buttons self.m_formatter = self.getFormatter() self.m_boldW = self.addToggleButton(self.m_toolbarPanel, Icons.bold_icon, "Bold") self.m_italicW = self.addToggleButton(self.m_toolbarPanel, Icons.italics_icon, "Italic") self.m_underlineW = self.addToggleButton(self.m_toolbarPanel, Icons.underline_icon, "Underline") self.m_subscriptW = self.addToggleButton(self.m_toolbarPanel, Icons.subscript_icon, "Subscript") self.m_superscriptW = self.addToggleButton(self.m_toolbarPanel, Icons.superscript_icon, "Superscript") self.m_strikethroughW = self.addToggleButton(self.m_toolbarPanel, Icons.strikethrough_icon, "Strikethrough") self.m_indentW = self.addPushButton(self.m_toolbarPanel, Icons.indentmore_icon, "Indent Right") self.m_outdentW = self.addPushButton(self.m_toolbarPanel, Icons.indentless_icon, "Indent Left") self.m_justifyLeftW = self.addPushButton(self.m_toolbarPanel, Icons.justifyleft_icon, "Justify Left") self.m_justifyCenterW = self.addPushButton(self.m_toolbarPanel, Icons.justifycenter_icon, "Justify Center") self.m_justifyRightW = self.addPushButton(self.m_toolbarPanel, Icons.justifyright_icon, "Justify Right") self.m_hrW = self.addPushButton(self.m_toolbarPanel, Icons.horizontalrule_icon, "Horizontal Rule") self.m_olW = self.addPushButton(self.m_toolbarPanel, Icons.numberedlist_icon, "Numbered List") self.m_ulW = self.addPushButton(self.m_toolbarPanel, Icons.list_icon, "List") self.m_newLinkW = self.addPushButton(self.m_toolbarPanel, Icons.link_icon, "Link Document") self.m_removeFormatW = self.addPushButton(self.m_toolbarPanel, Icons.noformat_icon, "No Format") self.m_mainPanel.add(self.m_toolbarPanel, DockPanel.NORTH) self.m_mainPanel.add(self.m_textW, DockPanel.CENTER) self.initWidget(self.m_mainPanel) self.sinkEvents(Event.ONCLICK) def getFormatter(self): return self.m_textW.getExtendedFormatter() def getRichTextArea(self): return self.m_textW def addPushButton(self, panel, imagep, tip): img = Image(imagep) img.setWidth("20px") img.setHeight("20px") pb = PushButton(img) self.addAnyButton(panel, pb, tip) return pb def addToggleButton(self, panel, imagep, tip): img = Image(imagep) img.setWidth("20px") img.setHeight("20px") tb = ToggleButton(img) self.addAnyButton(panel, tb, tip) return tb def addAnyButton(self, panel, button, tip): button.addStyleName("richText-button") button.setTitle(tip) button.setWidth(BUTTON_WIDTH) button.setHeight("100%") panel.add(button) panel.setCellWidth(button, BUTTON_WIDTH) button.addClickListener(self) def onClick(self, sender): if sender == self.m_boldW: self.m_formatter.toggleBold() elif sender == self.m_italicW: self.m_formatter.toggleItalic() elif sender == self.m_underlineW: self.m_formatter.toggleUnderline() elif sender == self.m_subscriptW: self.m_formatter.toggleSubscript() elif sender == self.m_superscriptW: self.m_formatter.toggleSuperscript() elif sender == self.m_strikethroughW: self.m_formatter.toggleStrikethrough() elif sender == self.m_indentW: self.m_formatter.rightIndent() elif sender == self.m_outdentW: self.m_formatter.leftIndent() elif sender == self.m_justifyLeftW: self.m_formatter.setJustification(RichTextArea.Justification.LEFT) elif sender == self.m_justifyCenterW: self.m_formatter.setJustification(RichTextArea.Justification.CENTER) elif sender == self.m_justifyRightW: self.m_formatter.setJustification(RichTextArea.Justification.RIGHT) elif sender == self.m_hrW: self.m_formatter.insertHorizontalRule() elif sender == self.m_olW: self.m_formatter.insertOrderedList() elif sender == self.m_ulW: self.m_formatter.insertUnorderedList() elif sender == self.m_removeFormatW: self.m_formatter.removeFormat() elif sender == self.m_newLinkW: EventLinkPopup.open(self) elif sender == self.m_textW: self.updateStatus() self.checkForChange() def onKeyDown(self, sender, keycode, modifiers): pass def onKeyUp(self, sender, keycode, modifiers): if sender == self.m_textW: self.updateStatus() self.checkForChange() def onMouseLeave(self, event): pass def onMouseEnter(self, event): pass def onMouseUp(self, event, x, y): pass def onMouseMove(self, event, x, y): pass def onMouseDown(self, event, x, y): self.trigger = True def onFocus(self, event): pass def onLostFocus(self, event): self.checkForChange() def onMouseOut(self, event): if self.m_isInText and self.isOnTextBorder(event): self.m_isInText = False self.captureSelection() self.endSelTimer() def onMouseOver(self, event): if not self.m_isInText: self.m_isInText = True self.m_textW.setFocus(True) self.m_lastRange = None self.startSelTimer() """* * This captures the selection when the mouse leaves the RTE, because in IE * the selection indicating the cursor position is lost once another widget * gains focus. Could be implemented for IE only. """ def captureSelection(self): try: self.getSelection() self.m_lastRange = Selection.getRange() except: GWT.log("Error capturing selection for IE", ex) # Gets run every time the selection is changed def onSelectionChange(self, sel): pass def isOnTextBorder(self, event): sender = event.getSource() twX = self.m_textW.getAbsoluteLeft() twY = self.m_textW.getAbsoluteTop() x = event.getClientX() - twX y = event.getClientY() - twY width = self.m_textW.getOffsetWidth() height = self.m_textW.getOffsetHeight() return ((sender == self.m_textW) and ((x <= 0) or (x >= width) or (y <= 0) or (y >= height))) def startSelTimer(self): self.m_selTimer.scheduleRepeating(250) def endSelTimer(self): self.m_selTimer.cancel() def getRange(self): if self.m_lastRange is None: self.getSelection() return Selection.getRange() else: return self.m_lastRange def getSelection(self): res = None try: window = self.getWindow() Selection.getSelection(window) except: print "Error getting the selection" traceback.print_exc() def getWindow(self, iFrame=None): if iFrame is None: iFrame = self.m_textW.getElement() iFrameWin = iFrame.contentWindow or iFrame.contentDocument if not iFrameWin.document: iFrameWin = iFrameWin.parentNode # FBJS version of parentNode #print "getWindow", iFrameWin, dir(iFrameWin) return iFrameWin def getDocument(self): return Selection.getDocument(self.getWindow()) def setHtml(self, text): self.m_textW.setHTML(text) self.m_lastText = text def getHtml(self): return self.m_textW.getHTML() def checkForChange(self): text = self.m_textW.getHTML() if text != self.m_lastText: nEvt = doc().createEvent("HTMLEvents") nEvt.initEvent("change", False, True) self.getElement().dispatchEvent(nEvt) self.m_lastText = text # Update edit buttons based on current cursor location def updateStatus(self): if self.m_formatter is None: return self.m_boldW.setDown(self.m_formatter.isBold()) self.m_italicW.setDown(self.m_formatter.isItalic()) self.m_underlineW.setDown(self.m_formatter.isUnderlined()) self.m_subscriptW.setDown(self.m_formatter.isSubscript()) self.m_superscriptW.setDown(self.m_formatter.isSuperscript()) self.m_strikethroughW.setDown(self.m_formatter.isStrikethrough()) def addChangeHandler(self, handler): return addDomHandler(handler, ChangeEvent.getType())