1#--------------------------------------------------------------------------- 2# Name: etg/_stc.py 3# Author: Robin Dunn 4# 5# Created: 24-Oct-2012 6# Copyright: (c) 2012-2018 by Total Control Software 7# License: wxWindows License 8#--------------------------------------------------------------------------- 9 10import etgtools 11import etgtools.tweaker_tools as tools 12 13PACKAGE = "wx" 14MODULE = "_stc" 15NAME = "_stc" # Base name of the file to generate to for this script 16DOCSTRING = """\ 17The :ref:`wx.stc.StyledTextCrtl` class provided by this module is a text widget 18primarily intended for use as a syntax highlighting source code editor. It is 19based on the popular Scintilla widget. 20""" 21 22# The classes and/or the basename of the Doxygen XML files to be processed by 23# this script. 24ITEMS = [ 'wxStyledTextCtrl', 25 'wxStyledTextEvent', 26 ] 27 28 29# The list of other ETG scripts and back-end generator modules that are 30# included as part of this module. These should all be items that are put in 31# the wxWidgets "stc" library in a multi-lib build. 32INCLUDES = [ ] 33 34 35# Separate the list into those that are generated from ETG scripts and the 36# rest. These lists can be used from the build scripts to get a list of 37# sources and/or additional dependencies when building this extension module. 38ETGFILES = ['etg/%s.py' % NAME] + tools.getEtgFiles(INCLUDES) 39DEPENDS = tools.getNonEtgFiles(INCLUDES) 40OTHERDEPS = [ ] 41 42 43#--------------------------------------------------------------------------- 44 45def run(): 46 # Parse the XML file(s) building a collection of Extractor objects 47 module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) 48 etgtools.parseDoxyXML(module, ITEMS) 49 module.check4unittest = False 50 51 #----------------------------------------------------------------- 52 # Tweak the parsed meta objects in the module object as needed for 53 # customizing the generated code and docstrings. 54 55 module.addHeaderCode('#include <wxPython/wxpy_api.h>') 56 module.addImport('_core') 57 module.addPyCode('''\ 58 import wx 59 ID_ANY = wx.ID_ANY # Needed for some parameter defaults in this module 60 ''', order=10) 61 module.addInclude(INCLUDES) 62 63 64 #----------------------------------------------------------------- 65 66 module.addHeaderCode('#include <wx/stc/stc.h>') 67 module.addHeaderCode('#include "wxpybuffer.h"') 68 69 70 c = module.find('wxStyledTextCtrl') 71 assert isinstance(c, etgtools.ClassDef) 72 c.bases = ['wxControl'] # wxTextCtrlIface is also a base... 73 c.piBases = ['wx.Control', 'wx.TextEntry'] 74 tools.fixWindowClass(c, False) 75 module.addGlobalStr('wxSTCNameStr', c) 76 77 78 c.find('GetCurLine.linePos').out = True 79 c.find('GetCurLineRaw.linePos').out = True 80 for name in ['Remove', 'Replace', 'SetSelection', 'GetSelection']: 81 m = c.find(name) 82 m.find('from').name = 'from_' 83 m.find('to').name = 'to_' 84 85 c.find('GetSelection.from_').out = True 86 c.find('GetSelection.to_').out = True 87 c.find('PositionToXY.x').out = True 88 c.find('PositionToXY.y').out = True 89 90 # Split the HitTest overloads into separately named methods since once 91 # the output parameters are applied they will have the same function 92 # signature. 93 ht1 = c.find('HitTest') 94 ht2 = ht1.overloads[0] 95 ht1.overloads = [] 96 c.insertItemAfter(ht1, ht2) 97 ht1.pyName = 'HitTestPos' 98 ht1.find('pos').out = True 99 ht2.find('row').out = True 100 ht2.find('col').out = True 101 102 103 # Replace the *Pointer methods with ones that return a memoryview object instead. 104 c.find('GetCharacterPointer').ignore() 105 c.addCppMethod('PyObject*', 'GetCharacterPointer', '()', 106 doc="""\ 107 Compact the document buffer and return a read-only memoryview 108 object of the characters in the document.""", 109 body=""" 110 const char* ptr = self->GetCharacterPointer(); 111 Py_ssize_t len = self->GetLength(); 112 PyObject* rv; 113 wxPyBLOCK_THREADS( rv = wxPyMakeBuffer((void*)ptr, len, true) ); 114 return rv; 115 """) 116 117 c.find('GetRangePointer').ignore() 118 c.addCppMethod('PyObject*', 'GetRangePointer', '(int position, int rangeLength)', 119 doc="""\ 120 Return a read-only pointer to a range of characters in the 121 document. May move the gap so that the range is contiguous, 122 but will only move up to rangeLength bytes.""", 123 body=""" 124 const char* ptr = self->GetRangePointer(position, rangeLength); 125 Py_ssize_t len = rangeLength; 126 PyObject* rv; 127 wxPyBLOCK_THREADS( rv = wxPyMakeBuffer((void*)ptr, len, true) ); 128 return rv; 129 """) 130 131 132 # Generate the code for this differently because it needs to be 133 # forcibly mashed into an int in the C code 134 module.find('wxSTC_MASK_FOLDERS').forcedInt = True 135 136 137 # Make sure that all the methods from wxTextEntry and wxTextCtrl are 138 # included. This is needed because we are pretending that this class only 139 # derives from wxControl but the real C++ class also derives from 140 # wxTextCtrlIface which derives from wxTextEntryBase. 141 import textentry 142 mod = textentry.parseAndTweakModule() 143 klass = mod.find('wxTextEntry') 144 items = [item for item in klass.items if isinstance(item, etgtools.MethodDef) and 145 not item.isCtor and 146 not item.isDtor and 147 not c.findItem(item.name)] 148 c.items.extend(items) 149 150 import textctrl 151 mod = textctrl.parseAndTweakModule() 152 klass = mod.find('wxTextCtrl') 153 items = [item for item in klass.items if isinstance(item, etgtools.MethodDef) and 154 not item.isCtor and 155 not item.isDtor and 156 not c.findItem(item.name)] 157 c.items.extend(items) 158 159 c.find('EmulateKeyPress').ignore() 160 c.find('IsMultiLine').ignore() 161 c.find('IsSingleLine').ignore() 162 c.find('MacCheckSpelling').ignore() 163 c.find('ShowNativeCaret').ignore() 164 c.find('HideNativeCaret').ignore() 165 166 # Change the *RGBAImage methods to accept any buffer object 167 c.find('MarkerDefineRGBAImage').ignore() 168 c.addCppMethod('void', 'MarkerDefineRGBAImage', '(int markerNumber, wxPyBuffer* pixels)', 169 doc="""\ 170 Define a marker from RGBA data.\n 171 It has the width and height from RGBAImageSetWidth/Height. You must 172 ensure that the buffer is at least width*height*4 bytes long. 173 """, 174 body="""\ 175 self->MarkerDefineRGBAImage(markerNumber, (unsigned char*)pixels->m_ptr); 176 """) 177 178 c.find('RegisterRGBAImage').ignore() 179 c.addCppMethod('void', 'RegisterRGBAImage', '(int type, wxPyBuffer* pixels)', 180 doc="""\ 181 Register an RGBA image for use in autocompletion lists.\n 182 It has the width and height from RGBAImageSetWidth/Height. You must 183 ensure that the buffer is at least width*height*4 bytes long. 184 """, 185 body="""\ 186 self->RegisterRGBAImage(type, (unsigned char*)pixels->m_ptr); 187 """) 188 189 190 # TODO: Add the UTF8 PyMethods from classic (see _stc_utf8_methods.py) 191 192 193 #----------------------------------------------------------------- 194 c = module.find('wxStyledTextEvent') 195 tools.fixEventClass(c) 196 197 module.addPyCode("""\ 198 EVT_STC_CHANGE = wx.PyEventBinder( wxEVT_STC_CHANGE, 1 ) 199 EVT_STC_STYLENEEDED = wx.PyEventBinder( wxEVT_STC_STYLENEEDED, 1 ) 200 EVT_STC_CHARADDED = wx.PyEventBinder( wxEVT_STC_CHARADDED, 1 ) 201 EVT_STC_SAVEPOINTREACHED = wx.PyEventBinder( wxEVT_STC_SAVEPOINTREACHED, 1 ) 202 EVT_STC_SAVEPOINTLEFT = wx.PyEventBinder( wxEVT_STC_SAVEPOINTLEFT, 1 ) 203 EVT_STC_ROMODIFYATTEMPT = wx.PyEventBinder( wxEVT_STC_ROMODIFYATTEMPT, 1 ) 204 EVT_STC_KEY = wx.PyEventBinder( wxEVT_STC_KEY, 1 ) 205 EVT_STC_DOUBLECLICK = wx.PyEventBinder( wxEVT_STC_DOUBLECLICK, 1 ) 206 EVT_STC_UPDATEUI = wx.PyEventBinder( wxEVT_STC_UPDATEUI, 1 ) 207 EVT_STC_MODIFIED = wx.PyEventBinder( wxEVT_STC_MODIFIED, 1 ) 208 EVT_STC_MACRORECORD = wx.PyEventBinder( wxEVT_STC_MACRORECORD, 1 ) 209 EVT_STC_MARGINCLICK = wx.PyEventBinder( wxEVT_STC_MARGINCLICK, 1 ) 210 EVT_STC_NEEDSHOWN = wx.PyEventBinder( wxEVT_STC_NEEDSHOWN, 1 ) 211 EVT_STC_PAINTED = wx.PyEventBinder( wxEVT_STC_PAINTED, 1 ) 212 EVT_STC_USERLISTSELECTION = wx.PyEventBinder( wxEVT_STC_USERLISTSELECTION, 1 ) 213 EVT_STC_URIDROPPED = wx.PyEventBinder( wxEVT_STC_URIDROPPED, 1 ) 214 EVT_STC_DWELLSTART = wx.PyEventBinder( wxEVT_STC_DWELLSTART, 1 ) 215 EVT_STC_DWELLEND = wx.PyEventBinder( wxEVT_STC_DWELLEND, 1 ) 216 EVT_STC_START_DRAG = wx.PyEventBinder( wxEVT_STC_START_DRAG, 1 ) 217 EVT_STC_DRAG_OVER = wx.PyEventBinder( wxEVT_STC_DRAG_OVER, 1 ) 218 EVT_STC_DO_DROP = wx.PyEventBinder( wxEVT_STC_DO_DROP, 1 ) 219 EVT_STC_ZOOM = wx.PyEventBinder( wxEVT_STC_ZOOM, 1 ) 220 EVT_STC_HOTSPOT_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_CLICK, 1 ) 221 EVT_STC_HOTSPOT_DCLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_DCLICK, 1 ) 222 EVT_STC_HOTSPOT_RELEASE_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_RELEASE_CLICK, 1 ) 223 EVT_STC_CALLTIP_CLICK = wx.PyEventBinder( wxEVT_STC_CALLTIP_CLICK, 1 ) 224 EVT_STC_AUTOCOMP_SELECTION = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_SELECTION, 1 ) 225 EVT_STC_INDICATOR_CLICK = wx.PyEventBinder( wxEVT_STC_INDICATOR_CLICK, 1 ) 226 EVT_STC_INDICATOR_RELEASE = wx.PyEventBinder( wxEVT_STC_INDICATOR_RELEASE, 1 ) 227 EVT_STC_AUTOCOMP_CANCELLED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_CANCELLED, 1 ) 228 EVT_STC_AUTOCOMP_CHAR_DELETED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_CHAR_DELETED, 1 ) 229 """) 230 231 #----------------------------------------------------------------- 232 233 234 #----------------------------------------------------------------- 235 tools.doCommonTweaks(module) 236 tools.runGenerators(module) 237 238 239 240#--------------------------------------------------------------------------- 241 242if __name__ == '__main__': 243 run() 244